Implementing Accessibility
1. Using Accessibility Props
| Prop | Description | Values | Notes |
|---|---|---|---|
| accessibilityLabel | Sets the accessibility label for a component | string |
Used by screen readers to announce the component's purpose |
| accessibilityHint | Provides a hint about the action that will occur when the component is touched | string |
Helps users understand what will happen when they interact with the component |
| accessibilityRole | Defines the role of a component in the accessibility tree | button, link, text, image, header, etc. |
Overrides the default role inferred by React Native |
| accessibilityState | Indicates the current state of a component (e.g., checked, disabled) | { expanded: boolean, selected: boolean, disabled: boolean } |
Used to communicate dynamic states to assistive technologies |
| accessibilityValue | Provides the current value of a component (e.g., slider, progress bar) | { min: number, max: number, now: number } |
Used to communicate the current value of interactive components |
| importantForAccessibility | Controls whether a component is included in the accessibility tree | auto, yes, no, no-hide-descendants |
Useful for hiding elements from screen readers without removing them from the DOM |
| accessibilityLiveRegion | Indicates how changes to a component should be announced by screen readers | none, polite, assertive |
Useful for live regions like notifications or updates |
Example: Using accessibilityLabel and accessibilityRole
<TouchableOpacity
accessibilityLabel="Press to navigate to the next screen"
accessibilityRole="button"
onPress={handlePress}
>
<Text>Next Screen</Text>
</TouchableOpacity>
Example: Using accessibilityState for a Toggle Button
<TouchableOpacity
accessibilityLabel="Toggle dark mode"
accessibilityRole="button"
accessibilityState={{ expanded: isDarkMode }}
onPress={toggleDarkMode}
>
<Text>Toggle Dark Mode</Text>
</TouchableOpacity>
2. Implementing Screen Reader Support
| Property | Description | Values |
|---|---|---|
| accessibilityLabel | Text used by screen readers to identify the element | string |
| accessibilityHint | Short description of what happens when the element is activated | string |
| accessibilityRole | Defines the role of the element for screen readers | button, text, image, link, header, navigation |
| accessibilityState | Indicates the current state of the element (e.g., checked, disabled) | { disabled: boolean, selected: boolean, checked: boolean } |
| importantForAccessibility | Controls whether the element is included in accessibility tree | auto, yes, no, no-hide-descendants |
Example: Using accessibilityLabel and accessibilityHint
<TouchableOpacity
accessibilityLabel="Save button"
accessibilityHint="Press to save your changes"
onPress={handleSave}
>
<Text>Save</Text>
</TouchableOpacity>
Example: Using accessibilityRole
<View accessibilityRole="header">
<Text>Welcome to the app</Text>
</View>
Example: Using accessibilityState
<Switch
accessibilityState={{ checked: isSwitchOn }}
onValueChange={toggleSwitch}
value={isSwitchOn}
>
Note: Screen reader support is critical for users with visual impairments. Always provide meaningful labels and hints to ensure accessibility compliance.
3. Using Accessibility Roles
| Role | Description | Usage |
|---|---|---|
| accessibilityRole | Defines the semantic role of an element for accessibility tools | <View accessibilityRole="button"> |
| alert | Indicates an alert or notification | <View accessibilityRole="alert"> |
| button | Represents a clickable button | <TouchableOpacity accessibilityRole="button"> |
| checkbox | Represents a checkbox input | <View accessibilityRole="checkbox"> |
| image | Indicates an image element | <Image accessibilityRole="image" source={...} /> |
| link | Represents a hyperlink | <Text accessibilityRole="link">Click here</Text> |
| menu | Represents a menu or dropdown | <View accessibilityRole="menu"> |
| menubar | Represents a menu bar | <View accessibilityRole="menubar"> |
| menuitem | Represents an item in a menu | <View accessibilityRole="menuitem"> |
| progressbar | Indicates a progress indicator | <View accessibilityRole="progressbar"> |
| radio | Represents a radio button | <View accessibilityRole="radio"> |
| radiogroup | Represents a group of radio buttons | <View accessibilityRole="radiogroup"> |
| scrollbar | Represents a scrollbar | <View accessibilityRole="scrollbar"> |
| spinbutton | Represents a spin button (numeric input) | <View accessibilityRole="spinbutton"> |
| switch | Represents a toggle switch | <View accessibilityRole="switch"> |
| tab | Represents a tab in a tabbed interface | <View accessibilityRole="tab"> |
| tabpanel | Represents a tab panel content area | <View accessibilityRole="tabpanel"> |
| text | Represents a text element | <Text accessibilityRole="text">Hello</Text> |
| toolbar | Represents a toolbar or set of controls | <View accessibilityRole="toolbar"> |
Example: Using accessibilityRole with TouchableOpacity
<TouchableOpacity
accessibilityRole="button"
onPress={handlePress}
>
<Text>Press Me</Text>
</TouchableOpacity>
Example: Using accessibilityRole with Image
<Image
accessibilityRole="image"
source={{ uri: "https://example.com/image.jpg" }}
accessible={true}
>
</Image>
4. Setting Accessibility Hints
| Property | Values | Description |
|---|---|---|
| accessibilityHint | string |
Provides a hint to the user about the action that will occur when they interact with the element. |
Example: Using accessibilityHint
<TouchableOpacity
accessibilityHint="Taps this button to navigate to the next screen"
onPress={handleNextScreen}
>
<Text>Go to Next Screen</Text>
</TouchableOpacity>
Note: The
accessibilityHint is used in conjunction with accessibilityLabel to provide more context for users who rely on assistive technologies.
5. Handling Accessibility States
| State | Description | Usage |
|---|---|---|
| accessible | Boolean indicating if the element is accessible | accessible={true} |
| accessibilityLabel | String used by screen readers to identify the element | accessibilityLabel="Submit Button" |
| accessibilityHint | Short description of what happens when the element is activated | accessibilityHint="Taps to submit form" |
| accessibilityRole | Defines the semantic role of the element | accessibilityRole="button" |
| accessibilityState | Object defining the current state of the element (e.g., disabled, selected) | accessibilityState={{selected: true}} |
Example: Using accessibilityState
<TouchableOpacity
accessibilityState={{disabled: true}}
accessible={true}
>
<Text>Disabled Button</Text>
</TouchableOpacity>
Example: Toggle accessibilityState
const [isSelected, setIsSelected] = useState(false);
<TouchableOpacity
accessibilityState={{selected: isSelected}}
onPress={() => setIsSelected(!isSelected)}
>
<Text>Toggle Selection</Text>
</TouchableOpacity>
6. Implementing Focus Management
| Property | Description | Usage |
|---|---|---|
| accessibilityFocus | Indicates whether the view should receive focus | <View accessibilityFocus={true} /> |
| focusable | Controls whether the view is focusable | <TouchableOpacity focusable={true} /> |
Example: Managing Focus in a List
import React, { useRef } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
const FocusList = () => {
const itemRefs = useRef([]);
const handleFocus = (index) => {
if (itemRefs.current[index]) {
itemRefs.current[index].setFocus();
}
};
return (
<View>
{'items'.map((item, index) => (
<TouchableOpacity
key={index}
ref={(ref) => itemRefs.current[index] = ref}
accessibilityFocus={index === 0}
onPress={() => handleFocus(index)}
>
<Text>{item}</Text>
</TouchableOpacity>
))}
</View>
);
};
Note: Use
accessibilityFocus to programmatically set focus on a component.
Warning: Ensure all focusable elements have a clear visual indicator.
7. Using AccessibilityInfo API
| Method | Description | Return Type | Notes |
|---|---|---|---|
| isBoldTextEnabled() | Checks if bold text is enabled | Promise<boolean> |
Available on iOS and Android |
| isHighContrastEnabled() | Checks if high contrast mode is enabled | Promise<boolean> |
Available on iOS and Android |
| isInvertColorsEnabled() | Checks if invert colors is enabled | Promise<boolean> |
Available on iOS and Android |
| isReduceTransparencyEnabled() | Checks if reduce transparency is enabled | Promise<boolean> |
Available on iOS and Android |
| isReduceMotionEnabled() | Checks if reduce motion is enabled | Promise<boolean> |
Available on iOS and Android |
| isScreenReaderEnabled() | Checks if a screen reader is enabled | Promise<boolean> |
Available on iOS and Android |
Example: Checking Screen Reader Status
import { AccessibilityInfo } from 'react-native';
const checkScreenReader = async () => {
const screenReaderEnabled = await AccessibilityInfo.isScreenReaderEnabled();
console.log('Screen reader enabled:', screenReaderEnabled);
};
checkScreenReader();
Example: Listening to Accessibility Changes
import { AccessibilityInfo } from 'react-native';
const handleScreenReaderChange = (screenReaderEnabled) => {
console.log('Screen reader status changed:', screenReaderEnabled);
};
const subscribeToChanges = () => {
const subscription = AccessibilityInfo.addEventListener(
'screenReaderChanged',
handleScreenReaderChange
);
return subscription;
};
const unsubscribe = subscribeToChanges();
8. Testing with Screen Readers
Example: Basic Accessibility Test Setup
import { Accessibility } from 'react-native';
// Check if accessibility is enabled
const isAccessible = Accessibility.isScreenReaderEnabled();
console.log('Screen reader enabled:', isAccessible);
| Method | Description | Return Type |
|---|---|---|
| isScreenReaderEnabled() | Checks if a screen reader is currently enabled | Promise<boolean> |
| announceForAccessibility() | Announces text to screen readers | void |
| setAccessibilityFocus() | Moves accessibility focus to a specific element | void |
Testing Workflow
- Enable screen reader on device/emulator
- Run app with accessibility features enabled
- Use
announceForAccessibilityto test announcements - Verify focus moves correctly with
setAccessibilityFocus - Check for visual feedback in accessibility mode
Note: Testing with screen readers requires actual device/emulator testing, as simulated environments may not fully replicate real user experiences.
9. Implementing Accessible Forms
| Property | Description | Usage |
|---|---|---|
| accessibilityLabel | Defines the label used by screen readers to identify the element. | <View accessibilityLabel="Submit Button"> |
| accessibilityHint | Provides a brief description of what happens when the element is activated. | <Button accessibilityHint="Taps to submit form"> |
| accessibilityRole | Defines the role of an element for assistive technologies. | <TextInput accessibilityRole="textbox"> |
| accessibilityState | Indicates the current state of an element (e.g., disabled, checked). | <CheckBox accessibilityState={{checked: true}}> |
| accessible | Controls whether an element is accessible to screen readers. | <View accessible={false}> |
Example: Accessible Form Fields
<View>
<TextInput
accessibilityLabel="Email Address"
accessibilityHint="Enter your email address"
placeholder="Email"
/>
<Button
accessibilityLabel="Submit Form"
accessibilityHint="Taps to submit form"
title="Submit"
/>
</View>
Note: Always ensure that form fields have descriptive
accessibilityLabel values and provide context with accessibilityHint.
Warning: Avoid using
accessible={false} unless necessary, as it disables accessibility for the element and its children.
10. Using Accessibility Live Regions
Accessibility live regions allow screen readers to announce dynamic content changes without requiring focus to be moved. They are particularly useful for updating status messages, notifications, or real-time data.
| Property | Values | Description |
|---|---|---|
| accessibilityLiveRegion | "polite", "assertive", "off" |
Defines how the screen reader should announce changes to the content. "polite" waits for a natural pause, "assertive" interrupts immediately, and "off" disables announcements. |
Example: Using accessibilityLiveRegion
<View accessibilityLiveRegion="polite">
<Text>Current status: {status}</Text>
</View>
Note: The
accessibilityLiveRegion property should be applied to a parent view that contains the content that will change dynamically. It is not effective when applied directly to text or other components.
11. Handling Dynamic Content Announcements
| Property | Description | Usage |
|---|---|---|
| accessibilityLiveRegion | Indicates to accessibility services when content changes dynamically | none, polite, assertive |
| accessibilityAnnouncement | Triggers an announcement for screen readers | Used with AccessibilityInfo |
Example: Using accessibilityLiveRegion
import { Text, View } from 'react-native';
const DynamicContent = () => {
const [message, setMessage] = useState('Initial message');
return (
<View>
<Text accessibilityLiveRegion="polite">{message}</Text>
<Button title="Update Message" onPress={() => setMessage('Updated message')} />
</View>
);
};
Example: Announcing Dynamic Updates
import { AccessibilityInfo } from 'react-native';
const announceUpdate = () => {
AccessibilityInfo.announceForAccessibility('New content has been loaded');
};
Note:
accessibilityLiveRegion should be used for content that updates without user interaction, such as notifications or live data feeds.