Skip to content

Commit

Permalink
use platform labels on the Accessibility page (#1948)
Browse files Browse the repository at this point in the history
* order accessibilityRoles alphabetically
  • Loading branch information
Simek authored Jun 18, 2020
1 parent a52bb86 commit 0a1637b
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 65 deletions.
134 changes: 69 additions & 65 deletions docs/accessibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Both Android and iOS provide APIs for integrating apps with assistive technologi
## Accessibility properties

### `accessible` (Android, iOS)
### `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 selectable component. By default, all touchable elements are accessible.

Expand All @@ -25,7 +25,7 @@ On Android, `accessible={true}` property for a react-native View will be transla

In the above example, we can't get accessibility focus separately on 'text one' and 'text two'. Instead we get focus on a parent view with 'accessible' property.

### `accessibilityLabel` (Android, iOS)
### `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 VoiceOver know what element they have selected. VoiceOver will read this string when a user selects the associated element.

Expand All @@ -44,7 +44,7 @@ To use, set the `accessibilityLabel` property to a custom string on your View, T

In the above example, the `accessibilityLabel` on the TouchableOpacity element would default to "Press me!". The label is constructed by concatenating all Text node children separated by spaces.

### `accessibilityHint` (Android, iOS)
### `accessibilityHint`

An accessibility hint helps users understand what will happen when they perform an action on the accessibility element when that result is not clear from the accessibility label.

Expand All @@ -66,45 +66,66 @@ iOS In the above example, VoiceOver will read the hint after the label, if the u

Android In the above example, Talkback will read the hint after the label. At this time, hints cannot be turned off on Android.

### `accessibilityIgnoresInvertColors` (iOS)
### `accessibilityIgnoresInvertColors` <div class="label ios">iOS</div>

Inverting screen colors is an Accessibility feature that makes the iPhone and iPad easier on the eyes for some people with a sensitivity to brightness, easier to distinguish for some people with color blindness, and easier to make out for some people with low vision. However, sometimes you have views such as photos that you don't want to be inverted. In this case, you can set this property to be false so that these specific views won't have their colors inverted.

### `accessibilityRole` (Android, iOS)
### `accessibilityLiveRegion` <div class="label android">Android</div>

When components dynamically change, we want TalkBack to alert the end user. This is made possible by the `accessibilityLiveRegion` property. It can be set to `none`, `polite` and `assertive`:

- **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.

```jsx
<TouchableWithoutFeedback onPress={addOne}>
<View style={styles.embedded}>
<Text>Click me</Text>
</View>
</TouchableWithoutFeedback>
<Text accessibilityLiveRegion="polite">
Clicked {count} times
</Text>
```

In the above example method `addOne` changes the state variable `count`. As soon as an end user clicks the TouchableWithoutFeedback, TalkBack reads text in the Text view because of its `accessibilityLiveRegion="polite"` property.

### `accessibilityRole`

`accessibilityRole` communicates the purpose of a component to the user of an assistive technology.

`accessibilityRole` can be one of the following:

- **none** Used when the element has no role.
- **button** Used when the element should be treated as a button.
- **link** Used when the element should be treated as a link.
- **search** Used when the text field element should also be treated as a search field.
- **image** Used when the element should be treated as an image. Can be combined with button or link, for example.
- **keyboardkey** Used when the element acts as a keyboard key.
- **text** Used when the element should be treated as static text that cannot change.
- **adjustable** Used when an element can be "adjusted" (e.g. a slider).
- **imagebutton** Used when the element should be treated as a button and is also an image.
- **header** Used when an element acts as a header for a content section (e.g. the title of a navigation bar).
- **summary** Used when an element can be used to provide a quick summary of current conditions in the app when the app first launches.
- **alert** Used when an element contains important text to be presented to the user.
- **button** Used when the element should be treated as a button.
- **checkbox** Used when an element represents a checkbox which can be checked, unchecked, or have mixed checked state.
- **combobox** Used when an element represents a combo box, which allows the user to select among several choices.
- **header** Used when an element acts as a header for a content section (e.g. the title of a navigation bar).
- **image** Used when the element should be treated as an image. Can be combined with button or link, for example.
- **imagebutton** Used when the element should be treated as a button and is also an image.
- **keyboardkey** Used when the element acts as a keyboard key.
- **link** Used when the element should be treated as a link.
- **menu** Used when the component is a menu of choices.
- **menubar** Used when a component is a container of multiple menus.
- **menuitem** Used to represent an item within a menu.
- **none** Used when the element has no role.
- **progressbar** Used to represent a component which indicates progress of a task.
- **radio** Used to represent a radio button.
- **radiogroup** Used to represent a group of radio buttons.
- **scrollbar** Used to represent a scroll bar.
- **search** Used when the text field element should also be treated as a search field.
- **spinbutton** Used to represent a button which opens a list of choices.
- **summary** Used when an element can be used to provide a quick summary of current conditions in the app when the app first launches.
- **switch** Used to represent a switch which can be turned on and off.
- **tab** Used to represent a tab.
- **tablist** Used to represent a list of tabs.
- **text** Used when the element should be treated as static text that cannot change.
- **timer** Used to represent a timer.
- **toolbar** Used to represent a tool bar (a container of action buttons or components).

### `accessibilityState` (Android, iOS)
### `accessibilityState`

Describes the current state of a component to the user of an assistive technology.

Expand All @@ -120,7 +141,7 @@ Describes the current state of a component to the user of an assistive technolog

To use, set the `accessibilityState` to an object with a specific definition.

### `accessibilityValue` (Android, iOS)
### `accessibilityValue`

Represents the current value of a component. It can be a textual description of a component's value, or for range-based components, such as sliders and progress bars, it contains range information (minimum, current, and maximum).

Expand All @@ -133,52 +154,19 @@ Represents the current value of a component. It can be a textual description of
| now | The current value of this component's range. | integer | No |
| text | A textual description of this component's value. Will override `min`, `now`, and `max` if set. | string | No |

### `accessibilityViewIsModal` (iOS)
### `accessibilityViewIsModal` <div class="label ios">iOS</div>

A Boolean value indicating whether VoiceOver should ignore the elements within views that are siblings of the receiver.

For example, in a window that contains sibling views `A` and `B`, setting `accessibilityViewIsModal` to `true` on view `B` causes VoiceOver to ignore the elements in the view `A`. On the other hand, if view `B` contains a child view `C` and you set `accessibilityViewIsModal` to `true` on view `C`, VoiceOver does not ignore the elements in view `A`.

### `accessibilityElementsHidden` (iOS)
### `accessibilityElementsHidden` <div class="label ios">iOS</div>

A Boolean value indicating whether the accessibility elements contained within this accessibility element are hidden.

For example, in a window that contains sibling views `A` and `B`, setting `accessibilityElementsHidden` to `true` on view `B` causes VoiceOver to ignore the elements in the view `B`. This is similar to the Android property `importantForAccessibility="no-hide-descendants"`.

### `onAccessibilityTap` (Android, iOS)

Use this property to assign a custom function to be called when someone activates an accessible element by double tapping on it while it's selected.

### `onMagicTap` (iOS)

Assign this property to a custom function which will be called when someone performs the "magic tap" gesture, which is a double-tap with two fingers. A magic tap function should perform the most relevant action a user could take on a component. In the Phone app on iPhone, a magic tap answers a phone call, or ends the current one. If the selected element does not have an `onMagicTap` function, the system will traverse up the view hierarchy until it finds a view that does.

### `onAccessibilityEscape` (iOS)

Assign this property to a custom function which will be called when someone performs the "escape" gesture, which is a two finger Z shaped gesture. An escape function should move back hierarchically in the user interface. This can mean moving up or back in a navigation hierarchy or dismissing a modal user interface. If the selected element does not have an `onAccessibilityEscape` function, the system will attempt to traverse up the view hierarchy until it finds a view that does or bonk to indicate it was unable to find one.

### `accessibilityLiveRegion` (Android)

When components dynamically change, we want TalkBack to alert the end user. This is made possible by the `accessibilityLiveRegion` property. It can be set to `none`, `polite` and `assertive`:

- **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.

```jsx
<TouchableWithoutFeedback onPress={addOne}>
<View style={styles.embedded}>
<Text>Click me</Text>
</View>
</TouchableWithoutFeedback>
<Text accessibilityLiveRegion="polite">
Clicked {count} times
</Text>
```

In the above example method `addOne` changes the state variable `count`. As soon as an end user clicks the TouchableWithoutFeedback, TalkBack reads text in the Text view because of its `accessibilityLiveRegion="polite"` property.

### `importantForAccessibility` (Android)
### `importantForAccessibility` <div class="label android">Android</div>

In the case of two overlapping UI components with the same parent, default accessibility focus can have unpredictable behavior. The `importantForAccessibility` property will resolve this by controlling if a view fires accessibility events and if it is reported to accessibility services. It can be set to `auto`, `yes`, `no` and `no-hide-descendants` (the last value will force accessibility services to ignore the component and all of its children).

Expand All @@ -199,6 +187,18 @@ In the case of two overlapping UI components with the same parent, default acces

In the above example, the `yellow` layout and its descendants are completely invisible to TalkBack and all other accessibility services. So we can use overlapping views with the same parent without confusing TalkBack.

### `onAccessibilityEscape` <div class="label ios">iOS</div>

Assign this property to a custom function which will be called when someone performs the "escape" gesture, which is a two finger Z shaped gesture. An escape function should move back hierarchically in the user interface. This can mean moving up or back in a navigation hierarchy or dismissing a modal user interface. If the selected element does not have an `onAccessibilityEscape` function, the system will attempt to traverse up the view hierarchy until it finds a view that does or bonk to indicate it was unable to find one.

### `onAccessibilityTap`

Use this property to assign a custom function to be called when someone activates an accessible element by double tapping on it while it's selected.

### `onMagicTap` <div class="label ios">iOS</div>

Assign this property to a custom function which will be called when someone performs the "magic tap" gesture, which is a double-tap with two fingers. A magic tap function should perform the most relevant action a user could take on a component. In the Phone app on iPhone, a magic tap answers a phone call, or ends the current one. If the selected element does not have an `onMagicTap` function, the system will traverse up the view hierarchy until it finds a view that does.

## Accessibility Actions

Accessibility actions allow an assistive technology to programmatically invoke the actions of a component. In order to support accessibility actions, a component must do two things:
Expand Down Expand Up @@ -256,30 +256,26 @@ To handle action requests, a component must implement an `onAccessibilityAction`

The `AccessibilityInfo` API allows you to determine whether or not a screen reader is currently active. See the [AccessibilityInfo documentation](accessibilityinfo) for details.

## Sending Accessibility Events (Android)
## Sending Accessibility Events <div class="label android">Android</div>

Sometimes it is useful to trigger an accessibility event on a UI component (i.e. when a custom view appears on a screen or set accessibility focus to a view). Native UIManager module exposes a method ‘sendAccessibilityEvent’ for this purpose. It takes two arguments: view tag and a type of an event. The supported event types are `typeWindowStateChanged`, `typeViewFocused` and `typeViewClicked`.

```jsx
import {Platform, UIManager, findNodeHandle} from 'react-native';
import {
Platform,
UIManager,
findNodeHandle
} from 'react-native';

if (Platform.OS === 'android') {
UIManager.sendAccessibilityEvent(
findNodeHandle(this),
UIManager.AccessibilityEventTypes.typeViewFocused,
UIManager.AccessibilityEventTypes.typeViewFocused
);
}
```

## Testing VoiceOver Support (iOS)

To enable VoiceOver, go to the Settings app on your iOS device (it's not available for simulator). Tap General, then Accessibility. There you will find many tools that people use to make their devices more usable, such as bolder text, increased contrast, and VoiceOver.

To enable VoiceOver, tap on VoiceOver under "Vision" and toggle the switch that appears at the top.

At the very bottom of the Accessibility settings, there is an "Accessibility Shortcut". You can use this to toggle VoiceOver by triple clicking the Home button.

## Testing TalkBack Support (Android)
## Testing TalkBack Support <div class="label android">Android</div>

To enable TalkBack, go to the Settings app on your Android device or emulator. Tap Accessibility, then TalkBack. Toggle the "Use service" switch to enable or disable it.

Expand All @@ -302,6 +298,14 @@ adb shell settings put secure enabled_accessibility_services com.android.talkbac
adb shell settings put secure enabled_accessibility_services com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService
```

## Testing VoiceOver Support <div class="label ios">iOS</div>

To enable VoiceOver, go to the Settings app on your iOS device (it's not available for simulator). Tap General, then Accessibility. There you will find many tools that people use to make their devices more usable, such as bolder text, increased contrast, and VoiceOver.

To enable VoiceOver, tap on VoiceOver under "Vision" and toggle the switch that appears at the top.

At the very bottom of the Accessibility settings, there is an "Accessibility Shortcut". You can use this to toggle VoiceOver by triple clicking the Home button.

## Additional Resources

- [Making React Native Apps Accessible](https://engineering.fb.com/ios/making-react-native-apps-accessible/)
6 changes: 6 additions & 0 deletions website/static/css/docs.css
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ figcaption {
border-right-color: #6170af;
}

h2 .label {
top: -6px;
margin-left: 12px;
}

h3 .label {
top: -2px;
margin-left: 22px;
Expand Down Expand Up @@ -301,6 +306,7 @@ td .label.required {
white-space: nowrap;
overflow: hidden;
color: transparent;
top: -1px;
}

/* Custom */
Expand Down

0 comments on commit 0a1637b

Please sign in to comment.