Describe the Feature
This is a proposed tweak to *ByRole query. It can be treated as either a fix or a (breaking) change.
Currently getByRole query is based on explicit role set in accessibilityRole prop. Other props are not taken into account (at least until #1064 is merged). This behaviour while basic can be problematic as according to screen readers, elements with accessible={false} (either explicit or implicit) are not focusable by screen reader.
This manifests in relatively common RN pattern:
<Pressable accessibilityRole="button" accessible={false}>
<Text>Cell title</Text>
<Pressable accessibilityRole="button">
<Text>Action</Text>
</Pressable>
</Pressable>
Under current implementation getByRole('button', { name: "Action" }) would select both outer and inner pressables. After implementing the proposed change it would select only the inner one.
Possible Implementations
- element can be matched by
getByRole using the same criteria as now (host component, equal accessibilityRole) but also needs to be considered accessibility element (i.e. be focusable).
- each host view can be made focusable by explicitly passing
accessible={true}
- some host view types are considered focusable without the
accessible prop (e.g. Text, TextInput), but can have their "focusability" disabled by setting accessible={false}
- basic host
View is not consider focusable
- some RN built in components, e.g.
Pressable, TouchableOpacity which render to host View actually set explicit accessible={true} prop on the view
In more practical terms we could use something like isAccessibilityElement to check for focusable state:
export function isAccessibilityElement(
element: ReactTestInstance | null
): boolean {
if (element == null) {
return false;
}
if (element.props.accessible !== undefined) {
return element.props.accessible;
}
return (
isHostElementForType(element, Text) ||
isHostElementForType(element, TextInput)
);
}
Then this criteria should be added to *ByRole query.
This change should not affect other general purpose queries as *ByText or *ByTestId. It may be worth considering applying it to some other a11y-related queries, which would make only sense if selected view is accessible: *ByA11yValue, *ByA11State.
Related Issues
#1152 - initial source for issue
#1163 - related discussion
#1064 - hidden query option
CC: @AugustinLF @pierrezimmermannbam @MattAgn @thymikee
Describe the Feature
This is a proposed tweak to
*ByRolequery. It can be treated as either a fix or a (breaking) change.Currently
getByRolequery is based on explicit role set inaccessibilityRoleprop. Other props are not taken into account (at least until #1064 is merged). This behaviour while basic can be problematic as according to screen readers, elements withaccessible={false}(either explicit or implicit) are not focusable by screen reader.This manifests in relatively common RN pattern:
Under current implementation
getByRole('button', { name: "Action" })would select both outer and inner pressables. After implementing the proposed change it would select only the inner one.Possible Implementations
getByRoleusing the same criteria as now (host component, equalaccessibilityRole) but also needs to be consideredaccessibility element(i.e. be focusable).accessible={true}accessibleprop (e.g.Text,TextInput), but can have their "focusability" disabled by settingaccessible={false}Viewis not consider focusablePressable,TouchableOpacitywhich render to hostViewactually set explicitaccessible={true}prop on the viewIn more practical terms we could use something like
isAccessibilityElementto check for focusable state:Then this criteria should be added to
*ByRolequery.This change should not affect other general purpose queries as
*ByTextor*ByTestId. It may be worth considering applying it to some other a11y-related queries, which would make only sense if selected view is accessible:*ByA11yValue,*ByA11State.Related Issues
#1152 - initial source for issue
#1163 - related discussion
#1064 - hidden query option
CC: @AugustinLF @pierrezimmermannbam @MattAgn @thymikee