Skip to content

Commit

Permalink
feat: Add aria-hidden prop to Pressable, View and Touchables componen…
Browse files Browse the repository at this point in the history
…ts (facebook#34552)

Summary:
This adds the ` aria-hidden` prop to `Pressable`, `TouchableBounce`, `TouchableHighlight`, `TouchableNativeFeedback`, `TouchableOpacity`, `TouchableWithoutFeedback` and `View` components as requested on facebook#34424, being an alias `importantforAccessibility='no-hide-descendants'` on Android and an alias for `accessibilityElementsHidden` on iOS. This PR also updates RNTester AccessibilityExample in order to facilitate the manual QA.

## Changelog

[General] [Added] -  Add aria-hidden prop to Pressable, View and Touchables components

Pull Request resolved: facebook#34552

Test Plan:
1. Open the RNTester app and navigate to the Accessibility page
2. Test the `aria-hidden` prop through the `View with hidden children from accessibility tree` section, this can be tested either by enabling Voice Over if you're using a real device or through the Accessibility Inspector if you're using a simulator

https://user-images.githubusercontent.com/11707729/187814455-6937e33e-7edd-434e-b7d3-ee6c03f635ca.mov

Reviewed By: NickGerleman

Differential Revision: D39206245

Pulled By: jacdebug

fbshipit-source-id: 551dc671fbcedc824f253e22b8d7753c466838c7
  • Loading branch information
gabrieldonadel authored and OlimpiaZurek committed May 22, 2023
1 parent 5971b59 commit ea5a3a5
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 13 deletions.
5 changes: 5 additions & 0 deletions Libraries/Components/Pressable/Pressable.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ type Props = $ReadOnly<{|
accessibilityValue?: ?AccessibilityValue,
accessibilityViewIsModal?: ?boolean,
accessible?: ?boolean,
/**
* A value indicating whether the accessibility elements contained within
* this accessibility element are hidden.
*/
'aria-hidden'?: ?boolean,
focusable?: ?boolean,
importantForAccessibility?: ?('auto' | 'yes' | 'no' | 'no-hide-descendants'),
onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed,
Expand Down
10 changes: 8 additions & 2 deletions Libraries/Components/Touchable/TouchableBounce.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,16 @@ class TouchableBounce extends React.Component<Props, State> {
accessibilityActions={this.props.accessibilityActions}
onAccessibilityAction={this.props.onAccessibilityAction}
accessibilityValue={this.props.accessibilityValue}
importantForAccessibility={this.props.importantForAccessibility}
importantForAccessibility={
this.props['aria-hidden'] === true
? 'no-hide-descendants'
: this.props.importantForAccessibility
}
accessibilityLiveRegion={this.props.accessibilityLiveRegion}
accessibilityViewIsModal={this.props.accessibilityViewIsModal}
accessibilityElementsHidden={this.props.accessibilityElementsHidden}
accessibilityElementsHidden={
this.props['aria-hidden'] ?? this.props.accessibilityElementsHidden
}
nativeID={this.props.nativeID}
testID={this.props.testID}
hitSlop={this.props.hitSlop}
Expand Down
10 changes: 8 additions & 2 deletions Libraries/Components/Touchable/TouchableHighlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,16 @@ class TouchableHighlight extends React.Component<Props, State> {
accessibilityValue={this.props.accessibilityValue}
accessibilityActions={this.props.accessibilityActions}
onAccessibilityAction={this.props.onAccessibilityAction}
importantForAccessibility={this.props.importantForAccessibility}
importantForAccessibility={
this.props['aria-hidden'] === true
? 'no-hide-descendants'
: this.props.importantForAccessibility
}
accessibilityLiveRegion={this.props.accessibilityLiveRegion}
accessibilityViewIsModal={this.props.accessibilityViewIsModal}
accessibilityElementsHidden={this.props.accessibilityElementsHidden}
accessibilityElementsHidden={
this.props['aria-hidden'] ?? this.props.accessibilityElementsHidden
}
style={StyleSheet.compose(
this.props.style,
this.state.extraStyles?.underlay,
Expand Down
8 changes: 6 additions & 2 deletions Libraries/Components/Touchable/TouchableNativeFeedback.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,10 +278,14 @@ class TouchableNativeFeedback extends React.Component<Props, State> {
accessibilityActions: this.props.accessibilityActions,
onAccessibilityAction: this.props.onAccessibilityAction,
accessibilityValue: this.props.accessibilityValue,
importantForAccessibility: this.props.importantForAccessibility,
importantForAccessibility:
this.props['aria-hidden'] === true
? 'no-hide-descendants'
: this.props.importantForAccessibility,
accessibilityLiveRegion: this.props.accessibilityLiveRegion,
accessibilityViewIsModal: this.props.accessibilityViewIsModal,
accessibilityElementsHidden: this.props.accessibilityElementsHidden,
accessibilityElementsHidden:
this.props['aria-hidden'] ?? this.props.accessibilityElementsHidden,
hasTVPreferredFocus: this.props.hasTVPreferredFocus,
hitSlop: this.props.hitSlop,
focusable:
Expand Down
10 changes: 8 additions & 2 deletions Libraries/Components/Touchable/TouchableOpacity.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,16 @@ class TouchableOpacity extends React.Component<Props, State> {
accessibilityActions={this.props.accessibilityActions}
onAccessibilityAction={this.props.onAccessibilityAction}
accessibilityValue={this.props.accessibilityValue}
importantForAccessibility={this.props.importantForAccessibility}
importantForAccessibility={
this.props['aria-hidden'] === true
? 'no-hide-descendants'
: this.props.importantForAccessibility
}
accessibilityLiveRegion={this.props.accessibilityLiveRegion}
accessibilityViewIsModal={this.props.accessibilityViewIsModal}
accessibilityElementsHidden={this.props.accessibilityElementsHidden}
accessibilityElementsHidden={
this.props['aria-hidden'] ?? this.props.accessibilityElementsHidden
}
style={[this.props.style, {opacity: this.state.anim}]}
nativeID={this.props.nativeID}
testID={this.props.testID}
Expand Down
10 changes: 8 additions & 2 deletions Libraries/Components/Touchable/TouchableWithoutFeedback.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type Props = $ReadOnly<{|
accessibilityValue?: ?AccessibilityValue,
accessibilityViewIsModal?: ?boolean,
accessible?: ?boolean,
'aria-hidden'?: ?boolean,
children?: ?React.Node,
delayLongPress?: ?number,
delayPressIn?: ?number,
Expand Down Expand Up @@ -71,7 +72,6 @@ type State = $ReadOnly<{|

const PASSTHROUGH_PROPS = [
'accessibilityActions',
'accessibilityElementsHidden',
'accessibilityHint',
'accessibilityLanguage',
'accessibilityIgnoresInvertColors',
Expand All @@ -81,7 +81,6 @@ const PASSTHROUGH_PROPS = [
'accessibilityValue',
'accessibilityViewIsModal',
'hitSlop',
'importantForAccessibility',
'nativeID',
'onAccessibilityAction',
'onBlur',
Expand Down Expand Up @@ -123,6 +122,13 @@ class TouchableWithoutFeedback extends React.Component<Props, State> {
: this.props.accessibilityState,
focusable:
this.props.focusable !== false && this.props.onPress !== undefined,

accessibilityElementsHidden:
this.props['aria-hidden'] ?? this.props.accessibilityElementsHidden,
importantForAccessibility:
this.props['aria-hidden'] === true
? 'no-hide-descendants'
: this.props.importantForAccessibility,
};
for (const prop of PASSTHROUGH_PROPS) {
if (this.props[prop] !== undefined) {
Expand Down
17 changes: 14 additions & 3 deletions Libraries/Components/View/View.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@ const View: React.AbstractComponent<
> = React.forwardRef(
(
{
tabIndex,
focusable,
role,
accessibilityElementsHidden,
accessibilityRole,
'aria-hidden': ariaHidden,
focusable,
importantForAccessibility,
pointerEvents,
role,
style,
tabIndex,
...otherProps
}: ViewProps,
forwardedRef,
Expand Down Expand Up @@ -118,6 +121,14 @@ const View: React.AbstractComponent<
accessibilityRole={
role ? roleToAccessibilityRoleMapping[role] : accessibilityRole
}
accessibilityElementsHidden={
ariaHidden ?? accessibilityElementsHidden
}
importantForAccessibility={
ariaHidden === true
? 'no-hide-descendants'
: importantForAccessibility
}
{...otherProps}
style={style}
pointerEvents={newPointerEvents}
Expand Down
8 changes: 8 additions & 0 deletions Libraries/Components/View/ViewPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,14 @@ export type ViewProps = $ReadOnly<{|
*/
accessibilityLabelledBy?: ?string | ?Array<string>,

/**
* A value indicating whether the accessibility elements contained within
* this accessibility element are hidden.
*
* See https://reactnative.dev/docs/view#aria-hidden
*/
'aria-hidden'?: ?boolean,

/**
* Views that are only used to layout their children or otherwise don't draw
* anything may be automatically removed from the native hierarchy as an
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ class AccessibilityExample extends React.Component<{}> {
</View>
</RNTesterBlock>

<RNTesterBlock title="View with hidden children from accessibility tree.">
<View aria-hidden>
<Text>
This view's children are hidden from the accessibility tree
</Text>
</View>
</RNTesterBlock>

{/* Android screen readers will say the accessibility hint instead of the text
since the view doesn't have a label. */}
<RNTesterBlock title="Accessible view with TextViews with hint">
Expand Down

0 comments on commit ea5a3a5

Please sign in to comment.