Skip to content

*ByRole: return only elements with implicit or explicit accessible={true} prop #1180

Description

@mdjastrzebski

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions