Search code examples
reactjsreact-nativeaccessibilityvoiceoverandroid-a11y

React native a11y: visually hide an element but make it available to screenreader


I have a View which contains a key and a value. The key is a string and the value is a numeric value, which represents whether something has gone up or down.

Visually, i use a chevron and turn the text to green or red, to show whether the value has gone up or down. Something similar to the below picture.

enter image description here

I want to make the chevron accessible to screenreaders, to make sure that screenreader announces "up by" or "down by" when the user focuses on the value. It seems this is possible by adding an accessibility label to the chevron, but the problem in my case is that i need to add accessible={true} to the container element otherwise voiceover does not announce the key and value together, instead it reads the key, moves to the next element on right, and once everything on the right is finished, it comes back and announces the value. By adding accessible={true}, i make sure that the key and value is announced together as one piece of information, but i lose the ability to add accessibilityLabel on individual children.

On web, i would have solved this problem by adding a screenreader only text which is visually hidden, on the chevron, but i am not really sure how to solve this in react native. Is there a preferred way?


Solution

  • Not deleting the question for others' reference, instead posting this as an answer.

    I was under the impression that when you set accessible={true} on the parent view, all the children accessibilityLabels are ignored, but it turns out that accessible={true} on the parent just makes the children unavailable for accessibility focus, but the accessibilityLabel is still respected. So in my case, this was easily solved with something like this:

    <View accessible={true}>
      <Text>
        key
      </Text>
      <Image accessibilityLabel={ diff > 0 ? 'up by' : 'down by' } source={chevron} />
        value
      </Text>
    </View>