facebook / react-native

A framework for building native applications using React
https://reactnative.dev
MIT License
118.46k stars 24.25k forks source link

iOS/Android: Customize the order of accessibility highlighting among sibling elements #30888

Closed amarlette closed 7 months ago

amarlette commented 3 years ago

Requires API Proposal

This issue requires a new API. An API proposal should be added and discussed before proceeding with implementation. The API proposal can be added in the comments of this issue or linked as a separate issue.

Description

It is currently impossible to specify the ordering of accessibility elements in RN. Talkback/Voiceover will read out elements in a predictable pattern, but this is not always a desired UX. There should be a way to set this for a particular view hierarchy.

React Native version:

v0.63

Expected Behavior

It is still up for discussion how this could actually look in React Native. To be completely stateless, there could be a "priority" assigned to each component that would dynamically dictate a traversal every time the views are updated. Alternatively, to more closely bridge to existing native constructs, an array of views or view references could be given as a way to dictate order.

Android Details

https://developer.android.com/reference/android/support/v4/view/accessibility/AccessibilityNodeInfoCompat.html#settraversalafter

iOS Details

https://developer.apple.com/documentation/uikit/accessibility/uiaccessibilitycontainer?language=objc

Related iOS docs: UIAccessibilityContainer, accessibilityElementAtIndex

SwiftUI (stateless) implementation: https://developer.apple.com/documentation/swiftui/view/accessibilitysortpriority(_:)

samithaf commented 3 years ago

@amarlette I am experiencing the same issue. I wonder is there a way to visually hide an element in React Native and only visible to screen readers? I have tried methods like setting height 0 and opacity 0 to a container and have the relevant text but voiceover does not seems to be picking up when the height is 0.

I have used various css tricks to do the same in web applications and worked perfectly well.

frags51 commented 3 years ago

Would be great to have a way to focus on elements without having a ref/direct editing control of components. Use case is that we might want to focus on elements which have been obtained from an external library, which does not expose a ref to their elements.

andriikovall commented 2 years ago

I am not sure if it's a good 3-rd party lib that doesn't expose refs to its elements. We use a solution with refs, what do you think about it?

This approach was used on IOS and view.setNextFocusForwardId and view.setAccessibilityTraversalBefore on Android

brunoprietog commented 2 years ago

@ZioVio That's great! Do you know if there is a way to convert it into a library and make it compatible with Expo? Unless this approach is approved from the React Native team, but it is likely to take a long time. Thanks!

fabien88 commented 2 years ago

I am not sure if it's a good 3-rd party lib that doesn't expose refs to its elements. We use a solution with refs, what do you think about it?

This approach was used on IOS and view.setNextFocusForwardId and view.setAccessibilityTraversalBefore on Android

We are using view.setAccessibilityTraversalBefore on android, it works well when components are visible on the screen, but it fails to focus in right order when next component is beneath the screen. Do you experiment the same issue @ZioVio ?

gaurav5430 commented 2 years ago

I have a use case for this, discussed here

https://stackoverflow.com/questions/73027686/react-native-a11y-grouping-elements-for-better-voiceover-announcement-while-sti

Since customizing the order of elements in not yet available, what are the currently suggested resolutions for such problems ?

andriikovall commented 1 year ago

@ziovio That's great! Do you know if there is a way to convert it into a library and make it compatible with Expo? Unless this approach is approved from the React Native team, but it is likely to take a long time. Thanks!

@brunoprietog

I might be way too late actually =) but expo provides a comprehensive list of tools available for customising native code for you https://docs.expo.dev/modules/overview/

As for the RN team, I am more than sure that it's not a priority and it's a lot simpler for them to let us, possible contributors, create a package for that

github-actions[bot] commented 7 months ago

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] commented 7 months ago

This issue was closed because it has been stalled for 7 days with no activity.

ArturKalach commented 1 month ago

Hello there,

I finished work on my own focus order library which should help with grouping and focus order. API is really simple and can help with horizontal scroll issue.

https://github.com/ArturKalach/react-native-a11y-order

For example:

import { A11y, IndexCommands } from 'react-native-a11y-order';

// ...

export default function App() {
  return (
    <ScrollView
      style={styles.slider}
      contentContainerStyle={styles.sliderContainer}
      horizontal
    >
      <A11y.Group style={styles.slide}>
        <View>
          <Text>Title: 1</Text>
        </View>
        <View>
          <Text>Desctiption: 1</Text>
        </View>
      </A11y.Group>
      <A11y.Group style={styles.slide}>
        <View>
          <Text>Title: 2</Text>
        </View>
        <View>
          <Text>Desctiption: 2</Text>
        </View>
      </A11y.Group>
    </ScrollView>
  );
}

And


import { A11y } from 'react-native-a11y-order';

// ...

export default function App() {
  return (
    <View style={styles.container}>
      <A11y.Order>
        <A11y.Index index={1}>
          <Text style={styles.font}>
            First
          </Text>
        </A11y.Index>
        <A11y.Index index={3}>
          <Text style={styles.font}>
            Third
          </Text>
        </A11y.Index>
        <A11y.Index index={2}>
          <Text style={styles.font}>
            Second
          </Text>
        </A11y.Index>
      </A11y.Order>
      <Text style={styles.font}>Fourth</Text>
      <Text style={styles.font}>Fifth</Text>
      <Text style={styles.font}>Sixth</Text>
    </View>
  );
}

We can use just indexes to define focus order.

brunoprietog commented 1 month ago

Awesome! Thanks @ArturKalach