Skip to content
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

Improvements to Android accessibility #168

Merged
merged 5 commits into from
May 19, 2020

Conversation

sfuqua
Copy link
Contributor

@sfuqua sfuqua commented Apr 16, 2020

Hi there - love this library but have run into some trouble with Android screen reader support:

  • Action sheet items don't have a role assigned; "button" is a good fit I think - iOS reads them as buttons
  • The rest of the app is still accessible behind the action sheet :(

I didn't see existing issues for these (especially the second one), and can open if desired!

This changes adds the Android-focused prop importantForAccessibility="yes" to the sheet while it's being rendered, as well as "no-hide-descendants" to the wrapped app content while the sheet is open. This ensures that only the action sheet content is accessible until it gets closed. This requires the app content to be wrapped in a new <View>, because there's no guarantee that the user is passing in something that takes accessibility props), but this seems to work out fine with flex: 1 (and react-native-action-sheet is adding its own wrapper already anyway).

I also added the "button" role to the action sheet options, and added a ref callback that will cause the screen reader to focus the first option/button in the list when the sheet opens (iOS has this behavior).

I tested this in my application and am happy with the results - our use case is rendering a React fragment inside of the ActionSheetProvider, I also tested it with a View being rendered as the child instead.

Also tested running the repo's example app on both my Android device (worked for all the examples) and the web variant. Verified that Narrator, using Edge on Windows, is reading the options as buttons now and no longer focuses the example app content while the sheet is open.

Happy to do additional testing if there scenarios that need to be covered.

New Android screen reader behavior (tested on a Galaxy S8, Android 9)

  • First option in the action sheet takes TalkBack focus when sheet pops up
  • Each option is read as a button by TalkBack
  • User can swipe left to focus the sheet itself and double tap to close/cancel or swipe right to enumerate the rest of the options; TalkBack cycles between the sheet and the last option and the rest of the app is not accessible until the sheet is closed

RN Documentation References:

@bradbyte
Copy link
Collaborator

@sfuqua thanks for this PR! I'm sorry I haven't reviewed it yet. Is there any customization that is needed to enable the equivalent for iOS (I know this implementation is Android only, but curious what the API is on iOS). Ideally, we'd match that as much as possible, my only thought is to make this configurable perhaps initially.

@sfuqua
Copy link
Contributor Author

sfuqua commented Apr 27, 2020

@sfuqua thanks for this PR! I'm sorry I haven't reviewed it yet. Is there any customization that is needed to enable the equivalent for iOS (I know this implementation is Android only, but curious what the API is on iOS). Ideally, we'd match that as much as possible, my only thought is to make this configurable perhaps initially.

@bradbumbalough It should work out of the box for iOS if I force iOS down the custom code path, but let me test that and get back to you.

@sfuqua
Copy link
Contributor Author

sfuqua commented Apr 28, 2020

@bradbumbalough I was unable to test functionality on iOS due to the lack of TouchableNativeFeedback support, but...

The Android importantForAccessibility prop won't impact iOS and the props added to the individual options are cross-platform; to get this working properly on iOS we would probably want to add the accessibilityViewIsModal prop to the action sheet which should have the same effect of hiding the siblings/app content from the screen reader.

In my latest push I added a disabled-by-default autoFocus prop to make the focus behavior opt-in, which should make this less risky. If you like I can try to to make the other changes with the new wrapper View opt-in as well, but that might be a little dirtier and I'd definitely want feedback on how to implement that (another new prop?).

FWIW if #169 is close to ready, I'd recommend pausing getting this in until after that change - would definitely want to test my changes again for compatibility with rendering in a modal.

@bradbyte
Copy link
Collaborator

bradbyte commented May 6, 2020

@sfuqua I'm sorry this has taken so long -- I was finally able to wrap up review of the modal PR, which introduced a conflict into this one. I can take a shot at the conflict as it looks pretty straight forward, but if you to pull down and update it I'll move to getting this in the next release.

@sfuqua
Copy link
Contributor Author

sfuqua commented May 6, 2020

@bradbumbalough no worries! I'll see if I can resolve conflicts today and re-test the changes in modal mode to make sure I didn't miss anything in that scenario.

@sfuqua sfuqua marked this pull request as draft May 6, 2020 16:22
@sfuqua
Copy link
Contributor Author

sfuqua commented May 6, 2020

@bradbumbalough merged and fixed a bug. Current status:

  • My change still works as expected with autoFocus prop and without modal mode
  • Focusing a button on mount seems to do nothing in modal mode - this is a frustrating problem I've had before with React Native modals and may be worth tracking as a separate bug, but I personally wouldn't block the PR on it. Still a large net improvement with the screen reader while the modal is up (I can traverse the action sheet just fine with VoiceOver and don't get "stuck" behind the action sheet).

If you like I can update the README to indicate autoFocus may be a no-op if used in combination with useModal, otherwise I'll leave this in your capable hands :)

@sfuqua sfuqua marked this pull request as ready for review May 6, 2020 17:25
@sfuqua
Copy link
Contributor Author

sfuqua commented May 13, 2020

Hi @bradbumbalough :) Do you have any concerns with this change that I can help with to get this merged?

@bradbyte
Copy link
Collaborator

This is really good. Great work @sfuqua, thank you for the contribution!

@bradbyte bradbyte merged commit b605fb8 into expo:master May 19, 2020
bradbyte pushed a commit that referenced this pull request May 19, 2020
# [3.8.0](v3.7.0...v3.8.0) (2020-05-19)

### Features

* Add destructiveColor option ([#171](#171)) ([5549e36](5549e36))
* Improvements to Android accessibility ([#168](#168)) ([b605fb8](b605fb8))
@bradbyte
Copy link
Collaborator

🎉 This PR is included in version 3.8.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@azanli azanli mentioned this pull request Jun 7, 2021