Switch Name

Link to Switch Name copied to clipboard

WCAG 2.0 - 4.1.2 A Impact - Critical

Any Switch element should have an accessible name available for assistive technologies such as TalkBack and Voice Access.

Impact

A switch should have a name that provides the context and expectation of what happens when it is turned on or off, especially for people with low-vision or blindness.

note

Issues may arise depending on the focus order of the switch and its name.

Confirmation

  1. Turn on TalkBack
  2. Attempt to focus on a Switch control
  3. One of the following will occur:
    • Inaccessible: TalkBack only announces 'on' or 'off'.
    • Accessible: TalkBack announces the name of the switch and 'on' or 'off'.

How to Fix

XML

You may provide a label in the neighboring element or wrap the switch with its label. You may also manipulate the contentDescription, but be sure to retain the 'on' and 'off' state for TalkBack announcements.

layouts/activity.xml
<TextView
     android:id="@+id/label"
     android:text="@string/label_text"
     android:labelFor="@+id/switch">
<Switch
     android:id="@+id/switch"/>

...

strings.values/
<string name="label_text">Dark Mode</string>

Compose

In the example below, put the Text and Switch together into a merged Compose layout like a Row. Add a switch role and toggleable modifier to the Text, then clear the semantics on the Switch by using Modifier.clearAndSetSemantics { } and it will make Talkback focus on the label but not the switch.

val (isSwitchChecked, setSwitchState) = remember { 
    mutableStateOf(true) 
}

Row(modifier = Modifier.semantics(mergeDescendants = true) { }) {
    Text(
        text = "Get Emails",
        modifier = Modifier
            .toggleable(
                value = isSwitchChecked,
                onValueChange = { 
                    setSwitchState(!isSwitchChecked) 
                },
                role = Role.Switch
            )
    )

    Switch(
        checked = isSwitchChecked,
        onCheckedChange = { 
            setSwitchState(!isSwitchChecked) 
        },
        modifier = Modifier
            .clearAndSetSemantics { }
    )
}

React Native

To combine a switch and label in React Native, you can wrap both components within a TouchableOpacity component:

<TouchableOpacity
   onPress={() => {
     setSwitchOn(!switchOn)
     Alert.alert("Switch on : " + !switchOn)}}
   style={styles.subContainer}
   accessible={true}
   accessibilityLabel={"Subscribe"}
   accessibilityRole='switch'>
      <Text style={{ fontSize: 22 }}>
         Subscribe
      </Text>
      <Switch
         importantForAccessibility='no-hide-descendants'
         onValueChange={() => {
            setSwitchOn(!switchOn)
            Alert.alert("Switch on : " + !switchOn)} }
        value={switchOn}
   />
</TouchableOpacity>

To ensure this functions well and provides all necessary context for both assistive technology and non-assistive technology users:

  • Ensure the TouchableOpacity view has the accessible property set to true, so that the group is focused together for assistive technology users.

  • Ensure the accessibilityLabel property of the TouchableOpacity component is set to the exact same value of the text label.

  • Set the TouchableOpacity component's accessibilityRole to switch to provide the correct context to assistive technology users.

  • Set the Switch component's importantForAccessibility property to no-hide-descendants so that the component cannot be individually focused.

  • Add an action via onPress to the TouchableOpacity component for handling the behavior of the switch when activated.