Skip to content

Accessibility Behavior

Maciej Jastrzebski edited this page Oct 8, 2022 · 11 revisions

Methods of testing:

  • iOS: using Accessibility Inspector (in iOS mode!) on iOS simulator
  • Android: using TalkBack on Android emulator

<Text> component

<Text> behavior in iOS

Component Screen reader Label Value Traits Identifier Hint User Input Label
<Text>Hello!</Text> Hello! Hello ! (none) Static Text (none) (none) Hello !
accessible={true} accessibilityRole="text" Hello! Hello ! (none) Static Text (none) (none) Hello !
accessible={true} Hello! Hello ! (none) Static Text (none) (none) Hello !
accessible={false} (ignored) (ignored) (ignored) (ignored) (ignored) (ignored) (ignored)
accessibilityRole="text" Hello! Hello ! (none) Static Text (none) (none) Hello !
accessibilityRole="none" Hello! Hello ! (none) (none) (none) (none) Hello !

Findings:

  • iOS behaves the same for when accessible={true} or when prop is not specified
  • iOS behaves the same for when accessibilityRole="text" or when prop is not specified
  • iOS ignores element when accessible={false}
  • changing accessibilityRole to "none" removes Static Text trait, but view is still readable by screen reader

<Text> behavior in Android

Component Screen reader
<Text >Hello!</Text> Hello!
accessible={true} accessibilityRole="text" Hello!
accessible={true} Hello!
accessible={false} Hello!
accessibilityRole="text" Hello!
accessibilityRole="none" Hello!
importantForAccessibility="no" (ignored)
importantForAccessibility="no-hide-descendants" (ignored)

Findings:

  • Android accessible props does not affect TalkBack screen reader behaviour
  • Android accessibilityRole props does not affect TalkBack screen reader behaviour
  • Android ignores element if importantForAccessibility value "no" or "no-hide-descendants"

<Text> handling recommendations

  • assume default accessible value of true
  • assume default accessibilityRole of text
  • assume none role when accessibilityRole="none"
  • assume excluded from accessibility when accessible={false} (based on iOS semantics)
  • assume excluded from accessibility role when importantForAccessibility="no" or importantForAccessibility="no-hide-descendants" (based on Android semantics)

<TextInput> component

<TextInput> behavior in iOS

Component Screen reader Label Value Traits Identifier Hint User Input Label
<TextInput defaultValue="Hello" /> Hello (none) Hello (empty) (none) (none) Hello
accessible={true} Hello (none) Hello (empty) (none) (none) Hello
accessible={false} Hello (none) Hello (empty) (none) (none) Hello
accessibilityRole="search Hello - search field (none) Hello Search Field (none) (none) Search Field
accessibilityRole="none" Hello (none) Hello (empty) (none) (none) Hello
editable={false} Hello - not enabled (none) Hello Not enabled (none) (none) Hello

Findings:

  • iOS ignores accessible={false} attribute, it behaves the same as default and true value
  • iOS ignores accessibilityRole="none" the elements behaves the same as without role attribute
  • iOS reacts to accessibilityRole="search" by reading the "serach field" trait name
  • iOS reacts to editable={false} by reading the "not enabled" trait name

<TextInput> behavior in Android

Component Screen reader
<TextInput defaultValue="Hello" /> Hello - edit box - double tap to edit text - double tap and hold to long press
accessible={true} Hello - edit box - double tap to edit text - double tap and hold to long press
accessible={false} Hello - edit box - double tap to edit text - double tap and hold to long press
accessibilityRole="search Hello - edit box - double tap to edit text - double tap and hold to long press
accessibilityRole="none Hello - edit box - double tap to activate - double tap and hold to long press
editable={false} Hello - edit box - disabled
importantForAccessibility="no" (ignored)
importantForAccessibility="no-hide-descendants" (ignored)

Findings:

  • Android ignores accessible={false} attribute, it behaves the same as default and true value
  • Android ignores accessibilityRole="search" the elements behaves the same as without role attribute
  • Android slight alters the read text when accessibilityRole="none", it says "double tap to activate" instead of "to edit text"

<TextInput> handling recommendations

  • assume "search" role when accessibilityRole="search"
  • assume excluded from accessibility role when importantForAccessibility="no" or importantForAccessibility="no-hide-descendants" (based on Android semantics)
  • assume accessibilityState disabled when editable={false}
  • consider assuming excluded from accessibility when accessible={false} (based on other elements behavior) TextInput behavior might be a bug
  • consider assuming implicit ARIA role of textbox when no explicit role is provided (based on the fact that Android reads "edit box" hint

<View> component

<View> behavior in iOS

Component Screen reader Label Value Traits Identifier Hint User Input Label
<View /> (ignored) (ignored) (ignored) (ignored) (ignored) (ignored) (ignored)
accessible={true} Description for element unavailable (none) (none) (empty) (none) (none) (Empty Array)
accessible={false} (ignored) (ignored) (ignored) (ignored) (ignored) (ignored) (ignored)
accessibilityRole="button" (ignored) (ignored) (ignored) (ignored) (ignored) (ignored) (ignored)
accessibilityRole="none" (ignored) (ignored) (ignored) (ignored) (ignored) (ignored) (ignored)
onPress={() => {}} (ignored) (ignored) (ignored) (ignored) (ignored) (ignored) (ignored)
accessible={true} accessibilityRole="button" Button (ignored) (ignored) Button (ignored) (ignored) (ignored)

Findings:

  • iOS ignores element when accessible={false} or when prop is not specified
  • iOS notices element when accessible={true}
  • iOS notices accessibilityRole only when accessible={true}
  • setting accessibilityRole or onPress alone does not affect iOS

<View> behavior in Android

Component Screen reader
<View /> (ignored)
accessible={true} (nothing, but focusable)
accessible={false} (ignored)
accessibilityRole="button" (ignored)
accessibilityRole="none" (ignored)
onPress={() => {}} (ignored)
accessible={true} accessibilityRole="button" Button - double tap to activate
importantForAccessibility="yes" (ignored)

Findings:

  • Android ignores element when accessible={false} or when prop is not specified
  • Android notices element when accessible={true} (becomes focusable)
  • Android notices accessibilityRole only when accessible={true} (reads the role)
  • setting accessibilityRole or onPress alone does not affect Android
  • Android ignores element if importantForAccessibility value "yes"

<View> handling recommendations

  • assume default accessible value of false
  • assume excluded from accessibility when accessible={false} or default
  • assume has default role "none" when accessible={true}