Permalink
Branch: master
Find file Copy path
4040151 Jan 22, 2019
1 contributor

Users who have contributed to this file

153 lines (117 sloc) 6.32 KB

Accessibility

On the Web, assistive technologies (e.g., VoiceOver, TalkBack screen readers) derive useful information about the structure, purpose, and interactivity of apps from their HTML elements, attributes, and ARIA in HTML. React Native for Web includes APIs designed to provide developers with support for making apps more accessible. The most common and best supported accessibility features of the Web are exposed as the props: accessible, accessibilityLabel, accessibilityLiveRegion, accessibilityRole, and importantForAccessibility.

Accessibility properties

accessible

When true, indicates that the view is an accessibility element. When a view is an accessibility element, it groups its children into a single focusable component. By default, all touchable elements, buttons, and links are "accessible". Prefer using accessibilityRole (e.g., button, link) to create focusable HTML elements wherever possible. On web, accessible={true} is implemented using tabIndex.

accessibilityLabel

When a view is marked as accessible, it is a good practice to set an accessibilityLabel on the view, so that people who use screen readers know what element they have selected. On web, accessibilityLabel is implemented using aria-label.

<TouchableOpacity accessibilityLabel={'Tap me!'} accessible={true} onPress={this._onPress}>
  <View style={styles.button}>
    <Text style={styles.buttonText}>Press me!</Text>
  </View>
</TouchableOpacity>

accessibilityLiveRegion

When components dynamically change we may need to inform the user. The accessibilityLiveRegion property serves this purpose and can be set to none, polite and assertive. On web, accessibilityLiveRegion is implemented using aria-live.

  • none: Accessibility services should not announce changes to this view.
  • polite: Accessibility services should announce changes to this view.
  • assertive: Accessibility services should interrupt ongoing speech to immediately announce changes to this view.
<TouchableWithoutFeedback onPress={this._addOne}>
  <View style={styles.embedded}>
    <Text>Click me</Text>
  </View>
</TouchableWithoutFeedback>

<Text accessibilityLiveRegion="polite">
  Clicked {this.state.count} times
</Text>

In the above example, method _addOne changes the state.count variable. As soon as an end user clicks the TouchableWithoutFeedback, screen readers announce text in the Text view because of its accessibilityLiveRegion="polite" property.

accessibilityRole

In some cases, we also want to alert the end user of the type of selected component (i.e., that it is a “button”). To provide more context to screen readers on the web, you should use the accessibilityRole property. (Note that React Native for Web also provides a compatibility mapping of equivalent accessibilityTraits and accessibilityComponentType values to accessibilityRole).

The accessibilityRole prop is used to infer an analogous HTML element and ARIA role, where possible. In most cases, both the element and ARIA role are rendered. While this may contradict some ARIA recommendations, it also helps avoid certain browser bugs, HTML5 conformance errors, and accessibility anti-patterns (e.g., giving a heading role to a button element). On the Web, accessibilityRole supports more values than React Native does for Andriod and iOS.

Straight-forward examples:

  • <View accessibilityRole="article" /> => <article role="article" />.
  • <View accessibilityRole="banner" /> => <header role="banner" />.
  • <Text accessibilityRole="label" /> => <label />.
  • <Text accessibilityRole="link" /> => <a role="link" />.
  • <View accessibilityRole="main" /> => <main role="main" />.

The heading role can be combined with aria-level:

  • <Text accessibilityRole="heading" /> => <h1 />.
  • <Text accessibilityRole="heading" aria-level="3" /> => <h3 />.

The button role renders an accessible button but is not implemented using the native button element due to some browsers limiting the use of flexbox layout on its children.

  • <View accessibilityRole="button" /> => <div role="button" tabIndex="0" />.

In the example below, the TouchableHighlight is announced by screen readers as a button and it responds to touch, mouse, and keyboard interactions.

<TouchableHighlight accessibilityRole="button" onPress={this._handlePress}>
  <View style={styles.button}>
    <Text style={styles.buttonText}>Press me!</Text>
  </View>
</TouchableHighlight>

Note: Avoid changing accessibilityRole values over time or after user actions. Generally, accessibility APIs do not provide a means of notifying assistive technologies of a role value change.

accessibilityStates

The accessibilityStates prop is an array of values used to infer the analogous ARIA states, e.g., aria-disabled, aria-pressed, aria-selected. On the Web, accessibilityStates supports more values than React Native does for Andriod and iOS.

importantForAccessibility

The importantForAccessibility property controls if a view appears in the accessibility tree and if it is reported to accessibility services. On web, a value of no will remove a focusable element from the tab flow, and a value of no-hide-descendants will also hide the entire subtree from assistive technologies (this is implemented using aria-hidden).

Spatial navigation

Focus-based web UIs, e.g., for TVs and Game Consoles can implement TV remote control navigation outside of React using existing directional-focus libraries. Every DOM element that React Native considers focusable can be matched by the attribute data-focusable="true".

const focusableElements = document.querySelectorAll('[data-focusable="true"]');

Other

Other ARIA properties can be set via direct manipulation or props (this may change in the future).