-
Notifications
You must be signed in to change notification settings - Fork 24.2k
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
Added talkback support for button accessibility: disabled prop #31001
Conversation
Hi @huzaifaaak! Thank you for your pull request and welcome to our community. Action RequiredIn order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you. ProcessIn order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with If you have received this in error or have any questions, please contact us at [email protected]. Thanks! |
Base commit: 4170726 |
Base commit: 4170726 |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
…ate. Also, fixed linting errors
…react-native into accessibility/button
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
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.
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
4 similar comments
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
@kacieb Can you please review this and give your comments 🙏 |
Libraries/Components/Button.js
Outdated
@@ -273,11 +278,14 @@ class Button extends React.Component<ButtonProps> { | |||
buttonStyles.push({backgroundColor: color}); | |||
} | |||
} | |||
const accessibilityState = {}; | |||
const accessibilityState = | |||
disabled != null |
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.
I'd suggest const accessibilityState = disabled === true ? ... : ...
so it's accessiblityState.disabled | disabled
.
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.
Sorry to follow up on this can we avoid creating a new object here?
const accessibilityState = disabled !== accessibilityState.disabled ? {...this.props.accessibilityState, disabled} : this.props.accessibilityState
Thanks for adding an example as well! |
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.
@@ -172,10 +172,14 @@ class ModalExample extends React.Component<{...}, $FlowFixMeState> { | |||
this.setState({currentOrientation: evt.nativeEvent.orientation}) | |||
} | |||
onDismiss={() => { | |||
if (this.state.action === 'onDismiss') alert(this.state.action); | |||
if (this.state.action === 'onDismiss') { | |||
alert(this.state.action); |
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.
no-alert: Unexpected alert.
}} | ||
onShow={() => { | ||
if (this.state.action === 'onShow') alert(this.state.action); | ||
if (this.state.action === 'onShow') { | ||
alert(this.state.action); |
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.
no-alert: Unexpected alert.
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.
Looks good to me!
@@ -18,7 +18,7 @@ const Text = require('../Text/Text'); | |||
const TouchableNativeFeedback = require('./Touchable/TouchableNativeFeedback'); | |||
const TouchableOpacity = require('./Touchable/TouchableOpacity'); | |||
const View = require('./View/View'); | |||
|
|||
import type {AccessibilityState} from './View/ViewAccessibility'; |
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.
Nit: should this also be grouped with line 24? I can also fix this on import
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.
Yes, this should be grouped with other type imports 💯. Please fix this during import
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.
@lunaleaps has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
if (disabled) { | ||
buttonStyles.push(styles.buttonDisabled); | ||
textStyles.push(styles.textDisabled); | ||
accessibilityState.disabled = true; |
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.
@kacieb brought up a great point -- this PR doesn't seem to be fixing accessibility for talkback but rather adding an ability for accessibilityState -- I tested on an Android device and did notice that talkback does announce "disabled" for the button in your example where you solely use accessibilityState
.
That raises the question of what was the original issue reporting? Was it reporting that accessibilityState={{disabled..
wasn't working -- which is indeed what your PR fixes -- but the fact that the property didn't even exist before has me puzzled
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.
cc @blavalla who reported the issue for clarification -- relevant to our discussion on disabled vs. accessibilityState.disabled
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.
I'm going to hold off landing this PR until we have some clarity about what the original issue is.
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.
Noted!
Link to the accessibility issue: #30840
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.
@lunaleaps, the original issue was that setting accessibilityState: disabled
alone was not actually disabling the button for accessibility.
This snack (https://snack.expo.io/d1Ikg7nqo) from #30840 shows the issue well.
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.
To clarify further, the issue was mostly that it is weird that you can actually set conflicting states for accessibility and non-accessibility users. Basically, there is nothing stopping someone from setting disabled="true"
accessibilityState={{disabled: false}}
or vice-versa.
If we are going to explicitly allow this though, they should at least work as expected, with the accessibilityState: disabled actually disabling the element for accessibility users.
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.
Ah right! . My mistake! Okay that clarifies things! It sounds like this change is still worth pursuing -- to just sync the two valuesaccessibilityState
is a View level prop so it should already exist on <Button />
Edit: Ah right because the snack does not have Flow enabled, it didn't warn by the fact that accessibiltyState
isn't a prop on Button.
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.
If we are going to explicitly allow this though, they should at least work as expected, with the accessibilityState: disabled actually disabling the element for accessibility users.
@lunaleaps I explicitly tested disabled="false"
and accessibilityState={{disabled: true}}
and it announces that button is disabled but it does not disables the onPress. I believe this needs to be done on the View level.
Having two different props is confusing. To disable the onPress we have to explicitly
pass the disabled={true}
prop.
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.
and it announces that button is disabled but it does not disables the onPress. I believe this needs to be done on the View level.
Yea I think that's covered by #30943
I think we should set this down for a bit and circle back to how we should handle these two props
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.
Otherwise looks good to me
Libraries/Components/Button.js
Outdated
@@ -273,11 +278,14 @@ class Button extends React.Component<ButtonProps> { | |||
buttonStyles.push({backgroundColor: color}); | |||
} | |||
} | |||
const accessibilityState = {}; | |||
const accessibilityState = | |||
disabled != null |
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.
Sorry to follow up on this can we avoid creating a new object here?
const accessibilityState = disabled !== accessibilityState.disabled ? {...this.props.accessibilityState, disabled} : this.props.accessibilityState
@lunaleaps I have updated it to avoid object creation. Do let me know if it can be done in a better way |
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.
@lunaleaps has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
@lunaleaps merged this pull request in 5889cbe. |
This is awesome, thank you so much for working on this and improving React Native's accessibility! I'd love to see a snapshot test for this component at some point, similar to this Pressable one added here, that ensures the |
Hey @huzaifaaak I would like to give you a shout-out on Twitter and include you in our end-of-month issues update for your contribution. Do you have a Twitter we can tag and is your @ the same as your Github? |
Hey @amarlette yes my twitter handle is the same huzaifaaak |
Summary: This PR aims to add test's for button. Snapshot test for PR #31001 . This would make sure `accessibilityState` is properly set. ## 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 --> [General] [Added] - Test's for button Pull Request resolved: #31189 Test Plan: `npm test` to run the test's. Since the disabled prop of button has precedence over `accessibilityState.disabled` the test's will make sure it remains this way. Reviewed By: kacieb Differential Revision: D27473082 Pulled By: lunaleaps fbshipit-source-id: 65d82620e8c245c2a8e29c3e9a8252d3a4275b09
Summary
Issue # #30934 .When using a screen reader disabled buttons do not announce that they are disabled.
Changelog
[Android] [Changed] - Passing accessibility state in button so it can announce disabled in talkback
Test Plan
I have added Button in Button Example with accessibiltyState prop that will announce button is disabled when testing with talkback.
Ios test
I am unable to run ios project on my machine. RNTesterPods.xcworkspace gives workspace integrity error :/