Skip to content

Commit

Permalink
feat: adding aria-label alias for accessibilityLabel (facebook#34502)
Browse files Browse the repository at this point in the history
Summary:
- Adding [aria-label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label) alias for [accessibilityLabel](https://reactnative.dev/docs/accessibility#accessibilitylabel)

facebook#34424

## Changelog

[General] [Added] - Add `aria-label` prop to `Button`, `View`, `Pressable` component

Pull Request resolved: facebook#34502

Test Plan:
```
<Button
     onPress={() => onButtonPress('cancelled')}
     testID="cancel_button"
     color={theme.SystemRedColor}
     title="Cancel Application"
     aria-lable="Press to cancel your application!"
/>
```

Reviewed By: NickGerleman

Differential Revision: D39055178

Pulled By: cipolleschi

fbshipit-source-id: 7513a4518dedd0834e99fa8e72b07e0dc0132b41
  • Loading branch information
Viraj-10 authored and OlimpiaZurek committed May 22, 2023
1 parent aa58858 commit 9883330
Show file tree
Hide file tree
Showing 18 changed files with 117 additions and 7 deletions.
6 changes: 5 additions & 1 deletion Libraries/Components/Button.flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,11 @@ type ButtonProps = $ReadOnly<{|
Text to display for blindness accessibility features.
*/
accessibilityLabel?: ?string,

/**
* Alias for accessibilityLabel https://reactnative.dev/docs/view#accessibilitylabel
* https://github.com/facebook/react-native/issues/34424
*/
'aria-label'?: ?string,
/**
If `true`, disable all interactions for this component.
Expand Down
9 changes: 7 additions & 2 deletions Libraries/Components/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,11 @@ type ButtonProps = $ReadOnly<{|
Text to display for blindness accessibility features.
*/
accessibilityLabel?: ?string,

/**
* Alias for accessibilityLabel https://reactnative.dev/docs/view#accessibilitylabel
* https://github.com/facebook/react-native/issues/34424
*/
'aria-label'?: ?string,
/**
If `true`, disable all interactions for this component.
Expand Down Expand Up @@ -286,6 +290,7 @@ class Button extends React.Component<ButtonProps> {
'aria-checked': ariaChecked,
'aria-disabled': ariaDisabled,
'aria-expanded': ariaExpanded,
'aria-label': ariaLabel,
'aria-selected': ariaSelected,
importantForAccessibility,
color,
Expand Down Expand Up @@ -358,7 +363,7 @@ class Button extends React.Component<ButtonProps> {
accessible={accessible}
accessibilityActions={accessibilityActions}
onAccessibilityAction={onAccessibilityAction}
accessibilityLabel={accessibilityLabel}
accessibilityLabel={ariaLabel || accessibilityLabel}
accessibilityHint={accessibilityHint}
accessibilityLanguage={accessibilityLanguage}
accessibilityRole="button"
Expand Down
8 changes: 8 additions & 0 deletions Libraries/Components/Pressable/Pressable.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,11 @@ type Props = $ReadOnly<{|
* Duration to wait after press down before calling `onPressIn`.
*/
unstable_pressDelay?: ?number,
/**
* Web to Native Accessibilty props
* https://github.com/facebook/react-native/issues/34424
*/
'aria-label'?: ?string,
|}>;

/**
Expand All @@ -204,6 +209,7 @@ function Pressable(props: Props, forwardedRef): React.Node {
'aria-checked': ariaChecked,
'aria-disabled': ariaDisabled,
'aria-expanded': ariaExpanded,
'aria-label': ariaLabel,
'aria-selected': ariaSelected,
cancelable,
children,
Expand Down Expand Up @@ -254,11 +260,13 @@ function Pressable(props: Props, forwardedRef): React.Node {
const accessibilityLiveRegion =
ariaLive === 'off' ? 'none' : ariaLive ?? props.accessibilityLiveRegion;

const accessibilityLabel = ariaLabel ?? props.accessibilityLabel;
const restPropsWithDefaults: React.ElementConfig<typeof View> = {
...restProps,
...android_rippleConfig?.viewProps,
accessible: accessible !== false,
accessibilityLiveRegion,
accessibilityLabel,
accessibilityState: _accessibilityState,
focusable: focusable !== false,
accessibilityValue,
Expand Down
4 changes: 3 additions & 1 deletion Libraries/Components/Touchable/TouchableBounce.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,13 @@ class TouchableBounce extends React.Component<Props, State> {
text: this.props['aria-valuetext'] ?? this.props.accessibilityValue?.text,
};

const accessibilityLabel =
this.props['aria-label'] ?? this.props.accessibilityLabel;
return (
<Animated.View
style={[{transform: [{scale: this.state.scale}]}, this.props.style]}
accessible={this.props.accessible !== false}
accessibilityLabel={this.props.accessibilityLabel}
accessibilityLabel={accessibilityLabel}
accessibilityHint={this.props.accessibilityHint}
accessibilityLanguage={this.props.accessibilityLanguage}
accessibilityRole={this.props.accessibilityRole}
Expand Down
4 changes: 3 additions & 1 deletion Libraries/Components/Touchable/TouchableHighlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,12 @@ class TouchableHighlight extends React.Component<Props, State> {
? 'none'
: this.props['aria-live'] ?? this.props.accessibilityLiveRegion;

const accessibilityLabel =
this.props['aria-label'] ?? this.props.accessibilityLabel;
return (
<View
accessible={this.props.accessible !== false}
accessibilityLabel={this.props.accessibilityLabel}
accessibilityLabel={accessibilityLabel}
accessibilityHint={this.props.accessibilityHint}
accessibilityLanguage={this.props.accessibilityLanguage}
accessibilityRole={this.props.accessibilityRole}
Expand Down
4 changes: 3 additions & 1 deletion Libraries/Components/Touchable/TouchableNativeFeedback.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ class TouchableNativeFeedback extends React.Component<Props, State> {
? 'none'
: this.props['aria-live'] ?? this.props.accessibilityLiveRegion;

const accessibilityLabel =
this.props['aria-label'] ?? this.props.accessibilityLabel;
return React.cloneElement(
element,
{
Expand All @@ -298,7 +300,7 @@ class TouchableNativeFeedback extends React.Component<Props, State> {
accessible: this.props.accessible !== false,
accessibilityHint: this.props.accessibilityHint,
accessibilityLanguage: this.props.accessibilityLanguage,
accessibilityLabel: this.props.accessibilityLabel,
accessibilityLabel: accessibilityLabel,
accessibilityRole: this.props.accessibilityRole,
accessibilityState: _accessibilityState,
accessibilityActions: this.props.accessibilityActions,
Expand Down
4 changes: 3 additions & 1 deletion Libraries/Components/Touchable/TouchableOpacity.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,12 @@ class TouchableOpacity extends React.Component<Props, State> {
? 'none'
: this.props['aria-live'] ?? this.props.accessibilityLiveRegion;

const accessibilityLabel =
this.props['aria-label'] ?? this.props.accessibilityLabel;
return (
<Animated.View
accessible={this.props.accessible !== false}
accessibilityLabel={this.props.accessibilityLabel}
accessibilityLabel={accessibilityLabel}
accessibilityHint={this.props.accessibilityHint}
accessibilityLanguage={this.props.accessibilityLanguage}
accessibilityRole={this.props.accessibilityRole}
Expand Down
1 change: 1 addition & 0 deletions Libraries/Components/Touchable/TouchableWithoutFeedback.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type Props = $ReadOnly<{|
'aria-selected'?: ?boolean,
'aria-hidden'?: ?boolean,
'aria-live'?: ?('polite' | 'assertive' | 'off'),
'aria-label'?: ?Stringish,
children?: ?React.Node,
delayLongPress?: ?number,
delayPressIn?: ?number,
Expand Down
3 changes: 3 additions & 0 deletions Libraries/Components/View/View.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ const View: React.AbstractComponent<
accessibilityElementsHidden,
accessibilityLiveRegion,
'aria-live': ariaLive,
accessibilityLabel,
accessibilityRole,
'aria-label': ariaLabel,
'aria-hidden': ariaHidden,
focusable,
importantForAccessibility,
Expand Down Expand Up @@ -148,6 +150,7 @@ const View: React.AbstractComponent<
accessibilityLiveRegion={
ariaLive === 'off' ? 'none' : ariaLive ?? accessibilityLiveRegion
}
accessibilityLabel={ariaLabel ?? accessibilityLabel}
focusable={tabIndex !== undefined ? !tabIndex : focusable}
accessibilityState={_accessibilityState}
accessibilityRole={
Expand Down
6 changes: 6 additions & 0 deletions Libraries/Components/View/ViewPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,12 @@ export type ViewProps = $ReadOnly<{|
*/
accessibilityHint?: ?Stringish,

/**
* Alias for accessibilityLabel https://reactnative.dev/docs/view#accessibilitylabel
* https://github.com/facebook/react-native/issues/34424
*/
'aria-label'?: ?Stringish,

/**
* Indicates to the accessibility services that the UI component is in
* a specific language. The provided string should be formatted following
Expand Down
1 change: 1 addition & 0 deletions Libraries/Image/Image.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => {
? loadingIndicatorSource.uri
: null,
ref: forwardedRef,
accessibilityLabel: props['aria-label'] ?? props.accessibilityLabel,
accessibilityState: {
busy: props['aria-busy'] ?? props.accessibilityState?.busy,
checked: props['aria-checked'] ?? props.accessibilityState?.checked,
Expand Down
2 changes: 2 additions & 0 deletions Libraries/Image/Image.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => {
expanded: ariaExpanded ?? props.accessibilityState?.expanded,
selected: ariaSelected ?? props.accessibilityState?.selected,
};
const accessibilityLabel = props['aria-label'] ?? props.accessibilityLabel;

return (
<ImageAnalyticsTagContext.Consumer>
Expand All @@ -172,6 +173,7 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => {
<ImageViewNativeComponent
accessibilityState={_accessibilityState}
{...restProps}
accessibilityLabel={accessibilityLabel}
ref={forwardedRef}
style={style}
resizeMode={resizeMode}
Expand Down
6 changes: 6 additions & 0 deletions Libraries/Image/ImageProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ export type ImageProps = {|
*/
accessibilityLabel?: ?Stringish,

/**
* Alias for accessibilityLabel
* See https://reactnative.dev/docs/image#accessibilitylabel
*/
'aria-label'?: ?Stringish,

/**
* blurRadius: the blur radius of the blur filter added to the image
*
Expand Down
4 changes: 4 additions & 0 deletions Libraries/Text/Text.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ const Text: React.AbstractComponent<
> = React.forwardRef((props: TextProps, forwardedRef) => {
const {
accessible,
accessibilityLabel,
allowFontScaling,
'aria-busy': ariaBusy,
'aria-checked': ariaChecked,
'aria-disabled': ariaDisabled,
'aria-expanded': ariaExpanded,
'aria-label': ariaLabel,
'aria-selected': ariaSelected,
ellipsizeMode,
onLongPress,
Expand Down Expand Up @@ -202,6 +204,7 @@ const Text: React.AbstractComponent<
{...restProps}
accessibilityState={_accessibilityState}
{...eventHandlersForText}
accessibilityLabel={ariaLabel ?? accessibilityLabel}
isHighlighted={isHighlighted}
isPressable={isPressable}
selectable={_selectable}
Expand All @@ -218,6 +221,7 @@ const Text: React.AbstractComponent<
disabled={_disabled}
selectable={_selectable}
accessible={_accessible}
accessibilityLabel={ariaLabel ?? accessibilityLabel}
accessibilityState={nativeTextAccessibilityState}
allowFontScaling={allowFontScaling !== false}
ellipsizeMode={ellipsizeMode ?? 'tail'}
Expand Down
1 change: 1 addition & 0 deletions Libraries/Text/TextProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export type TextProps = $ReadOnly<{|
accessibilityLabel?: ?Stringish,
accessibilityRole?: ?AccessibilityRole,
accessibilityState?: ?AccessibilityState,
'aria-label'?: ?string,

/**
* Whether font should be scaled down automatically.
Expand Down
22 changes: 22 additions & 0 deletions packages/rn-tester/js/examples/Button/ButtonExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,28 @@ exports.examples = [
);
},
},
{
title: 'Button with aria-label="label"',
description: ('Note: This prop changes the text that a screen ' +
'reader announces (there are no visual differences).': string),
render: function (): React.Node {
return (
<RNTesterThemeContext.Consumer>
{theme => {
return (
<Button
onPress={() => onButtonPress('submitted')}
testID="aria_label_button"
color={theme.LinkColor}
title="Submit Application"
aria-label="Press to submit your application!"
/>
);
}}
</RNTesterThemeContext.Consumer>
);
},
},
{
title: 'Button with accessibilityState={{disabled: true}}',
description:
Expand Down
27 changes: 27 additions & 0 deletions packages/rn-tester/js/examples/Pressable/PressableExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,16 @@ import {
Text,
Platform,
View,
Alert,
} from 'react-native';
import ReactNativeFeatureFlags from 'react-native/Libraries/ReactNative/ReactNativeFeatureFlags';

const {useEffect, useRef, useState} = React;

function onPressablePress(pressableName: string) {
Alert.alert(`Your application has been ${pressableName}!`);
}

const forceTouchAvailable =
(Platform.OS === 'ios' && Platform.constants.forceTouchAvailable) || false;

Expand Down Expand Up @@ -81,6 +86,20 @@ function TextOnPressBox() {
);
}

function PressableAriaLabel() {
return (
<View style={[styles.row, styles.centered]}>
<Pressable
style={styles.wrapper}
testID="pressable_aria_label"
aria-label="pressable with aria label"
accessibilityRole="button"
onPress={() => onPressablePress('pressed')}>
<Text style={styles.button}>Press Me</Text>
</Pressable>
</View>
);
}
function PressableFeedbackEvents() {
const [eventLog, setEventLog] = useState([]);

Expand Down Expand Up @@ -524,6 +543,14 @@ const examples = [
return <PressableDisabled />;
},
},
{
title: 'Pressable with aria-label="label"',
description: ('Note: This prop changes the text that a screen ' +
'reader announces (there are no visual differences).': string),
render: function (): React.Node {
return <PressableAriaLabel />;
},
},
];

if (ReactNativeFeatureFlags.shouldPressibilityUseW3CPointerEventsForHover()) {
Expand Down
12 changes: 12 additions & 0 deletions packages/rn-tester/js/examples/View/ViewExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -600,4 +600,16 @@ exports.examples = [
);
},
},
{
title: 'View with aria-label="label"',
render(): React.Node {
return (
<View
aria-label="Blue background View with Text"
style={{backgroundColor: '#527FE4', padding: 5}}>
<Text style={{fontSize: 11}}>Blue background</Text>
</View>
);
},
},
];

0 comments on commit 9883330

Please sign in to comment.