AccessibilityRole mapping limits for custom components across iOS and Android
0 reputation · 14 Dec 2022, 02:34 UTC
0 reputation · 14 Dec 2022, 02:34 UTC
When building custom composite components in React Native, teams often rely on the Accessibility API to expose correct semantics to screen readers. The accessibilityRole prop is intended to map a component to a native accessibility element, such as a button or header, on both iOS and Android. However, the exact boundaries of this mapping for custom components that wrap multiple native views remain unclear.
React Native translates accessibilityRole into platform-specific accessibility metadata—UIKit traits on iOS and class or role hints on Android via View and AccessibilityNodeInfo. Because custom components may combine several native elements, the resulting announcement can diverge between platforms. The interaction with the accessible prop, which flattens children into a single focusable element, adds further uncertainty about whether the parent role or child semantics take precedence.
Which accessibilityRole values are reliably mapped to equivalent native semantics for custom composite components across iOS and Android? Does grouping with the accessible prop change how the role is interpreted differently on each platform? Where can developers confirm the current cross-platform mapping behavior for a specific React Native version?
For a React Native custom component that wraps several native views, the only accessibilityRole values that consistently translate to the same native semantics on both iOS and Android are the standard roles listed in the official RN documentation:
All other strings are treated as undefined by the RN native modules. On iOS this results in the default UIAccessibilityTraitNone and on Android a generic AccessibilityNodeInfo with no role hint, so the screen reader will announce the component as an “unknown” element.
accessible on Role PrecedenceWhen accessible={true} is set on a parent view:
accessibilityRole supplied on the parent is applied to that node on both platforms.accessibilityElementsHidden={true} is also set, in which case the children remain in the tree but are hidden from the screen reader.Without accessible={true}, each child retains its own node and its role is announced independently. The parent’s role does not override the children’s semantics.
AccessibilityRole.js (or the corresponding native module) in the react-native repo and locate the mapping tables for iOS and Android. Verify that the role you plan to use appears in both lists.
import {View, Text} from "react-native";
export default () => (
<View accessible={true} accessibilityRole="button">
<Text>Submit</Text>
</View>
);
accessible={false} to observe that the child text is announced independently and the parent has no role.
1. React Native Docs. The accessibilityRole page lists the supported values for the current release.
2. RN source. The mapping tables in AccessibilityRole.js (Android) and AccessibilityRole.swift (iOS) are the definitive reference.
3. Platform Accessibility Inspector. The VoiceOver Inspector (macOS) and Android Accessibility Scanner provide runtime visibility into the node’s traits and role hints.
To give a more precise recommendation, could you confirm which React Native version (e.g., 0.73.4) and which iOS/Android OS builds you are targeting? The mapping tables can change between RN releases and OS updates.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.