Skip to main content
Version: Next

Accessibility States

Accessibility states are specific attributes that can be added to a component to communicate its current status to assistive technology.

aria-busy

• Severity: Serious

Indicates an element is being modified and that assistive technologies may want to wait until the changes are complete before informing the user about the update.[^1]

TypeDefault
booleanfalse

Expectations

Assistive Technology: Screen Reader
  • When: The user triggers (double tap) a component
    • And: The component is performing a long (or async) task
      • Then: The Screen Reader announces the component as busy

Screen Reader behaviour

Assuming we have a button that adds the given product ID to the cart, which requires an API call:

const AddToCart = ({ productID }: { productID: string }) => {
const { addToCart, isAddingToCart } = useQuery(ADD_TO_CART);

const onPress = async () => {
const result = await addToCart();
};

return (
<Pressable
accessibilityLabel="Add to cart"
accessibilityRole="button"
ariaBusy={isAddingToCart}
onPress={isAddingToCart ? undefined : onPress}
>
{isAddingToCart} ? <ActivityIndicator /> : <Text>Add to cart</Text>
</Pressable>
);
};

In the example, while the adding action is happening, the button:

  • Ignores any press action
  • Shows a loading spinner

While this works fine for sighted users, we must add the ariaBusy={isAddingToCart} property for visually impaired users to signal that the action is still happening.

The user double taps on the example component:

VoiceOverTalkback
plays a sound as confirmationGood

The user focuses again on the component while the API is still in flight:

VoiceOverTalkback
Add to cart, busy, button, double tap to activateGood

aria-checked

• Severity: Serious

Indicates the state of a checkable element. This field can either take a boolean or the "mixed" string to represent mixed checkboxes.

TypeDefault
boolean, 'mixed'false

Expectations

Assistive Technology: Screen Reader
  • When: The component can be toggle
    • And: Receives the focus
      • Then: The checked status is announced
      • And: And the accessibility label is announced
      • And: And the accessibility role is announced
      • And: And the available action is announced
caution

aria-checked is not to be confused with aria-selected. aria-checked is only meant to be used with checkboxes and toggle buttons.

Screen Reader behaviour

type ToggleButtonProps = {
checked: boolean;
label: string;
};

export const ToggleButton = ({ checked, label }: ToggleButtonProps) => {
return (
<Pressable
accessibilityLabel={label}
ariaChecked={checked}
ariaRole="button"
>
{label}
</Pressable>
);
};

Assuming the button label is: Add me to the list

The user selects the component

StateVoiceOverTalkback
checkedticked, Add me to the list, tickbox, double tap to toggleGood
not checkednot ticked, Add me to the list, tickbox, double tap to toggleGood

The user double taps on the example component:

New stateVoiceOverTalkback
checkedtickedGood
not checkednot tickedGood

aria-disabled

• Severity: Serious

Indicates that the element is perceivable but disabled, so it is not editable or otherwise operable.

TypeDefault
booleanfalse

Expectations

Assistive Technology: Screen Reader
  • When: The component is disabled
    • And: Receives the focus
      • Then: The Screen Reader announces its disabled status first
      • And: The accessibility label is announced
      • And: The accessibility role is announced

Screen Reader behaviour

const AddToCart = ({ disabled }) => {
return (
<Pressable
accessibilityLabel="Add to cart"
accessibilityRole="button"
disabled={disabled}
>
Add to cart
</Pressable>
);
};

When the component receives the focus

Is Disabled?VoiceOverTalkback
falseAdd me to the cart, button, double tap to activateAdd me to the cart, button, double tap to activateGood
truedimmed, Add me to the cart, buttondisabled, Add me to the cart, buttonGood

aria-expanded

• Severity: Serious

Indicates whether an expandable element is currently expanded or collapsed.

TypeDefault
booleanfalse

Expectations

Assistive Technology: Screen Reader
  • When: The user triggers (double tap) a collapsable component, i.e. Accordion
    • And: Its content is expanded/collapsed
      • Then: The Screen Reader announces the component as expanded/collapsed

Screen Reader behaviour

export const Content = ({ content }) => {
const [isShowingMore, setIsShowingMore] = React.useState(false);

return (
<View>
<Text numberOfLines={isShowingMore ? undefined : 2}>{content}</Text>
<Pressable
accessibilityLabel="Show more"
accessibilityRole="button"
ariaExpanded={isShowingMore}
onPress={() => setIsShowingMore(showMore => !showMore)}
>
{isShowingMore ? 'Show less' : 'Show more'}
</Pressable>
</View>
);
};

When the component receives the focus

Is the content expanded?VoiceOverTalkback
falseShow more, collapsed button, double tap to activateGood
trueShow less, expanded, button, double tap to activateGood

When the component is activated (double-tap)

Is the new state expanded?VoiceOverTalkback
falseShow more, collapsed button, double tap to activateGood
trueShow less, expanded, button, double tap to activateGood

aria-selected

Indicates whether a selectable element is currently selected or not.

TypeDefault
booleanfalse

Expectations

Assistive Technology: Screen Reader
  • When: The user selects an option component, i.e. radio button
    • Then: The Screen Reader announces the component selected state first

Screen Reader behaviour

const OptionButton = ({ selected, label }) => {
return (
<Pressable
accessibilityLabel={label}
accessibilityRole="button"
ariaSelected={selected}
>
<Text>{label}</Text>
</Pressable>
);
};

const TestScreen = () => {
const [selectedOption, setSelectedOption] = React.useState('Big');

return ['Big', 'Medium', 'Small'].map(size => {
return (
<Option
label={size}
selected={optionSelected}
onPress={() => setSelectedOption(size)}
/>
);
});
};

When the component receives the focus

Is Selected?VoiceOverTalkback
falseaccessibility label, button, double tap to activateGood
trueSelected, accessibility label button, double tap to activateGood

When the component is activated (double-tap)

Is the new state selected?VoiceOverTalkback
trueaccessibility label, selectedGood
falseGood

External references