Skip to content

[a11y] Nested accessibility items are not respected on iOS #24515

Open

Description

@sahrens

React Native apps often have many UI components that are touchable but also contain nested elements that are also touchable. For example, an entire list row may be touchable as a primary navigation option, but it might also have an auxiliary button nested inside of it for taking a specific action, like delete or save.

Currently, if the touchable wrapper for the auxiliary button as well as the row container are properly tagged with accessibility props and accessibility labels it works fine on Android but on iOS, the nested 'save/delete' button is not selectable by VoiceOver. On Android, both will be accessible when accessibility features are enabled.

The current workaround in user-land is to make some janky hierachry where the aux button is a sibling of its visual container, which often breaks encapsulation and is generally a pain.

There are a couple ways we might be able to work around this at the framework level:

  1. use UIAccessibilityContainer protocol
  2. set the accessibilityElements property on the parent

Those approaches are detailed a bit more here:
https://stackoverflow.com/questions/38849389/voiceover-parent-and-child-views-as-accessibility-elements

Looks like flutter had this same issue and fixed it here with UIAccessibilityContainer: flutter-team-archive/engine#4110

Tracked internally with T34121499

Activity

  1. react-native-bot commented on Apr 18, 2019

    @react-native-bot
    Collaborator

    Thanks for submitting your issue. Can you take another look at your description and make sure the issue template has been filled in its entirety?

    👉 Click here if you want to take another look at the Bug Report issue template.

  2. jessebeach commented on Apr 18, 2019

    @jessebeach

    @sahrens this is also true on Web for roles that flatten their children into text, known as childPresentational.

    https://www.w3.org/TR/wai-aria-1.1/#childrenArePresentational

    Only Android allows nesting of interactive accessibility nodes within interactive accessibility nodes. We should disallow this practice altogether at the React Native level in order to satisfy the constraints of all target platforms. React Native should throw a run-time error when this nesting is detected. That would solve a category of issues that we're constantly chasing down on iOS and Web.

  3. sahrens commented on Apr 19, 2019

    @sahrens
    ContributorAuthor

    @jessebeach: generally we try not to limit experiences based on lowest common denominator (especially if there are workarounds like flutter uses), but I agree we need to address this in a way that developers aren’t easily shooting themselves in the foot with a11y. Accessory buttons in list items are a particularly common pattern - what’s the recommended way to make them accessible?

    @necolas: how have you dealt with this on react-native-web?

  4. necolas commented on Apr 19, 2019

    @necolas

    I haven't yet. But I have been planning to add runtime errors when nesting elements with accessibilityRole of link or button to avoid people stumbling into these issues.

    You can still have nested Touchables without problem as long as the ancestral ones aren't given link or button roles. That allows mouse, touch, and keyboard interactions to function as expected but requires a little care if the functionality of the outer Touchable isn't redundant. Something like touching a twitter post navigates to the permalink, and the timestamp is marked up as a link for screen readers to be able to navigate there too. If you don't have redundancy you need to fall back to Touchables as siblings and use tricks like absolute positioning (emulating the background layer) to place them visually over each other.

  5. jessebeach commented on Apr 19, 2019

    @jessebeach

    If you don't have redundancy you need to fall back to Touchables as siblings and use tricks like absolute positioning (emulating the background layer) to place them visually over each other.

    Accessory buttons in list items are a particularly common pattern - what’s the recommended way to make them accessible?

    @necolas provided the answer here. The trick is to think of the link item not as the container, but as a sibling interactive element. The accessory buttons are siblings to it. The list item and the accessories are contained in a common parent node. The visual presentation gives the appearance of the list item interactive as the parent container, but that's just presentational fluff.

    That's one solution the developer can take. She might however decide to use aria-activedescendant on Web or Rotor secondary actions on iOS. This is an implementation detail and depends on the design. The takeaway is, there are ways to build around the no-nesting limitation in developer land.

  6. sahrens commented on Apr 19, 2019

    @sahrens
    ContributorAuthor
  7. necolas commented on Apr 19, 2019

    @necolas

    Turns out React already prints warnings to the console if you nest links or buttons.

    is it feasible on web too

    Not sure but it might be quite complicated as you'd need to preserve all the other expectations around nesting elements even thought they're not actually nested in the DOM.

  8. stale commented on Aug 4, 2019

    @stale

    Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

  9. added
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    on Aug 4, 2019
  10. stale commented on Aug 11, 2019

    @stale

    Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please feel free to create a new issue with up-to-date information.

  11. locked as resolved and limited conversation to collaborators on Aug 12, 2019
  12. added
    Never gets stalePrevent those issues and PRs from getting stale
    and removed
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    on Oct 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions