-
Notifications
You must be signed in to change notification settings - Fork 24.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Accessibility states API. #24608
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code analysis results:
eslint
found some issues. Runyarn lint --fix
to automatically fix problems.
Libraries/Components/Button.js
Outdated
if (disabled) { | ||
buttonStyles.push(styles.buttonDisabled); | ||
textStyles.push(styles.textDisabled); | ||
accessibilityStates.push('disabled'); | ||
accessibilityStates['enabled'] = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dot-notation: ["enabled"] is better written in dot notation.
|
For context, this is a change I proposed here to provide an API that works for platforms where attributes must be present on host nodes to communicate their purpose to the native accessibility system |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might need to support but deprecate the old API to give people time to migrate
ReactAndroid/src/main/java/com/facebook/react/uimanager/AccessibilityDelegateUtil.java
Outdated
Show resolved
Hide resolved
@necolas Any thoughts about how to deprecate the older API, while strongly encouraging developers to move to the new one? |
Hopefully someone from RN Core will be able to advise |
Ideally we make this a non-breaking change for now by supporting both arrays or objects for a while, then we’ll add a warning in the release after, and then release a codemod (I can help with that) and then remove it. |
600eb59
to
44bec03
Compare
@cpojer Not sure how to allow the native code to accept both an array of strings as well as an object. Any ideas? |
Unfortunately we can't make a breaking change like that in a single pull request. We could wrap |
@marcmulcahy do you have any idea for a new prop that we could introduce so that we could deprecate the existing one? I know this is unfortunate but it seems like the only way. If not, please close this PR. |
@cpojer I suppose we could simply add a new prop called something like accessibilityStates2 that's an object instead of an array of strings. Switch all the RNTester samples and components to use accessibilityStates2, and then eventually deprecate accessibilityStates, or rename accessibilityStates2 to accessibilityStates. I do think this object-based API is much clearer, in that the component author must enumerate the states that "matter", and it makes much clearer how states are related to each other (expanded/collapsed, checked/unchecked, etc.). I'm also happy to close the PR if this isn't something we want to tackle ATM. Let me know what FB prefers to do. |
Alright, yeah I think we can do this. Can you change this PR to do the following:
In a month from now (sorry, this is some fb internal issue we have to deal with) we can then change how accessibilityStates works as long as we don't have internal users for it any longer. A month after that we can bring back the accessibilityStates prop with the new API and kill the deprecatedAccessibilityStates API. I'm sorry for this slow multi process step but I think it's worth doing it if you are up for it :) |
Alternatively, if we can think of a better name than
What would be a reasonable name for a new prop? |
|
I think that’s a great idea. Let’s do it! |
44bec03
to
3e8420c
Compare
As we discussed, this version moves the new API to a new property called "accessibilityState" and leaves "accessibilityStates" in tact. To verify that the existing prop was still working, I applied all the patches which add the new property, and left RNTester unchanged, and verified that RNTester behaves as before on both Android and iOS. I then modified RNTester to use "accessibilityState" instead of "accessibilityStates" and re-tested. |
Looks good to me |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fantastic. Thank you so much @marcmulcahy and I'm sorry for putting you through so much pain with this one but I really appreciate you were sticking with us :)
I made a few small inline reverts to ensure the current props keep working at FB during the migration phase. Once this PR is landed, do you mind sending a PR that removes accessibilityStates
altogether? I can merge that one (in about a month from now) and then we'll be in a good state again :)
…t of strings contained in accessibilityStates with a more semantically rich object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cpojer is landing this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cpojer has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
This pull request was successfully merged by Marc Mulcahy in 099be9b. When will my fix make it into a release? | Upcoming Releases |
Summary: As currently defined, accessibilityStates is an array of strings, which represents the state of an object. The array of strings notion doesn't well encapsulate how various states are related, nor enforce any level of correctness. This PR converts accessibilityStates to an object with a specific definition. So, rather than: <View ... accessibilityStates={['unchecked']}> We have: <View accessibilityStates={{'checked': false}}> And specifically define the checked state to either take a boolean or the "mixed" string (to represent mixed checkboxes). We feel this API is easier to understand an implement, and provides better semantic definition of the states themselves, and how states are related to one another. ## Changelog [general] [change] - Convert accessibilityStates to an object instead of an array of strings. Pull Request resolved: facebook#24608 Differential Revision: D15467980 Pulled By: cpojer fbshipit-source-id: f0414c0ef6add3f10f7f551d323d82d978754278
…1144) Summary: This issue fixes #30955 and is a follow up to pr #24608 which added the basic Accessibility functionalities to React Native. TextInput should announce "selected" to the user when screenreader focused. The focus is moved to the TextInput by navigating with the screenreader to the TextInput. This PR adds call to View#setSelected in BaseViewManager https://developer.android.com/reference/android/view/View#setSelected(boolean) The View#setSelected method definition https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/view/View.java ```java /** * Changes the selection state of this view. A view can be selected or not. * Note that selection is not the same as focus. Views are typically * selected in the context of an AdapterView like ListView or GridView; * the selected view is the view that is highlighted. * * param selected true if the view must be selected, false otherwise */ public void setSelected(boolean selected) { if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) { // ... hidden logic if (selected) { sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); } // ... hidden logic } } ``` VoiceOver and TalkBack was tested with video samples included below. ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://github.com/facebook/react-native/wiki/Changelog --> [Android] [Fixed] - Fix Selected State does not announce when TextInput Component selected on Android Pull Request resolved: #31144 Test Plan: **<details><summary>CLICK TO OPEN TESTS RESULTS</summary>** <p> **ENABLE THE AUDIO** to hear the TalkBack announcing **SELECTED** when the user taps on the TextInput ```javascript <TextInput accessibilityLabel="element 20" accessibilityState={{ selected: true, }} /> ``` | selected is true | |:-------------------------:| | <video src="https://user-images.githubusercontent.com/24992535/111652826-afc4f000-8807-11eb-9c79-8c51d7bf455b.mp4" width="700" height="" /> | ```javascript <TextInput accessibilityLabel="element 20" accessibilityState={{ selected: false, }} /> ``` | selected is false | |:-------------------------:| | <video src="https://user-images.githubusercontent.com/24992535/111652919-c10dfc80-8807-11eb-8244-83db6c327bcd.mp4" width="700" height="" /> | The functionality does not present issues on iOS | iOS testing | |:-------------------------:| | <video src="https://user-images.githubusercontent.com/24992535/111647656-f401c180-8802-11eb-9fa9-a4c211cf1665.mp4" width="400" height="" /> | </p> </details> </p> </details> Reviewed By: blavalla Differential Revision: D27306166 Pulled By: kacieb fbshipit-source-id: 1b3cb37b2d0875cf53f6f1bff4bf095a877b2f0e
Summary
As currently defined, accessibilityStates is an array of strings, which represents the state of an object. The array of strings notion doesn't well encapsulate how various states are related, nor enforce any level of correctness.
This PR converts accessibilityStates to an object with a specific definition. So, rather than:
<View
...
accessibilityStates={['unchecked']}>
We have:
<View
accessibilityStates={{'checked': false}}>
And specifically define the checked state to either take a boolean or the "mixed" string (to represent mixed checkboxes).
We feel this API is easier to understand an implement, and provides better semantic definition of the states themselves, and how states are related to one another.
Changelog
[general] [change] - Convert accessibilityStates to an object instead of an array of strings.
Test Plan
Converted code in RNTester to use the new accessibilityStates API, and modified the checkbox example to support the "mixed" state, which was one of the limitations of the current API which prompted this work.