Skip to content

Commit

Permalink
feat : add aria labelled as alias for accessibilityLabelledBy (facebo…
Browse files Browse the repository at this point in the history
…ok#34725)

Summary:
This adds the [aria-labelledby](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-labelledby)  prop to the components where it's used as requested on facebook#34424,  equivalent [accessibilityLabelledBy](https://reactnative.dev/docs/accessibility#accessibilitylabelledby-android)

## Changelog
[General] [Added] - Add aria-modal prop to basic component

## TestPlan

 - Enable talkback.
 - Open the RNTester app and navigate to the Api's tab
 - Go to the TextInput with aria-labelledby attribute section

<img width="495" alt="Screenshot 2022-09-19 at 7 46 05 PM" src="https://user-images.githubusercontent.com/22423684/191038924-017dba93-ea7d-494d-ba6f-161e986f9b54.png">

Pull Request resolved: facebook#34725

Reviewed By: lunaleaps

Differential Revision: D40176143

Pulled By: lunaleaps

fbshipit-source-id: 003d1ab27bfd01b5c6d4c58a4de501ec7966359d
  • Loading branch information
Daksh Bhardwaj authored and OlimpiaZurek committed May 22, 2023
1 parent 36cb017 commit 6c939c0
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 21 deletions.
3 changes: 3 additions & 0 deletions Libraries/Components/TextInput/TextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,8 @@ function InternalTextInput(props: Props): React.Node {
} else if (Platform.OS === 'android') {
const style = [props.style];
const autoCapitalize = props.autoCapitalize || 'sentences';
const _accessibilityLabelledBy =
props?.['aria-labelledby'] ?? props?.accessibilityLabelledBy;
const placeholder = props.placeholder ?? '';
let children = props.children;
const childCount = React.Children.count(children);
Expand All @@ -1464,6 +1466,7 @@ function InternalTextInput(props: Props): React.Node {
{...eventHandlers}
accessible={accessible}
accessibilityState={_accessibilityState}
accessibilityLabelledBy={_accessibilityLabelledBy}
autoCapitalize={autoCapitalize}
submitBehavior={submitBehavior}
caretHidden={caretHidden}
Expand Down
48 changes: 28 additions & 20 deletions Libraries/Components/View/View.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,25 @@ const View: React.AbstractComponent<
(
{
accessibilityElementsHidden,
accessibilityLiveRegion,
'aria-live': ariaLive,
accessibilityLabel,
accessibilityLabelledBy,
accessibilityLiveRegion,
accessibilityRole,
'aria-label': ariaLabel,
accessibilityState,
accessibilityValue,
'aria-busy': ariaBusy,
'aria-checked': ariaChecked,
'aria-disabled': ariaDisabled,
'aria-expanded': ariaExpanded,
'aria-hidden': ariaHidden,
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledBy,
'aria-live': ariaLive,
'aria-selected': ariaSelected,
'aria-valuemax': ariaValueMax,
'aria-valuemin': ariaValueMin,
'aria-valuenow': ariaValueNow,
'aria-valuetext': ariaValueText,
focusable,
id,
importantForAccessibility,
Expand All @@ -49,14 +62,8 @@ const View: React.AbstractComponent<
}: ViewProps,
forwardedRef,
) => {
const {
accessibilityState,
'aria-busy': ariaBusy,
'aria-checked': ariaChecked,
'aria-disabled': ariaDisabled,
'aria-expanded': ariaExpanded,
'aria-selected': ariaSelected,
} = otherProps;
const _accessibilityLabelledBy =
ariaLabelledBy?.split(/\s*,\s*/g) ?? accessibilityLabelledBy;

const _accessibilityState = {
busy: ariaBusy ?? accessibilityState?.busy,
Expand All @@ -66,6 +73,13 @@ const View: React.AbstractComponent<
selected: ariaSelected ?? accessibilityState?.selected,
};

const _accessibilityValue = {
max: ariaValueMax ?? accessibilityValue?.max,
min: ariaValueMin ?? accessibilityValue?.min,
now: ariaValueNow ?? accessibilityValue?.now,
text: ariaValueText ?? accessibilityValue?.text,
};

// Map role values to AccessibilityRole values
const roleToAccessibilityRoleMapping = {
alert: 'alert',
Expand Down Expand Up @@ -134,20 +148,13 @@ const View: React.AbstractComponent<
treeitem: undefined,
};

const accessibilityValue = {
max: otherProps['aria-valuemax'] ?? otherProps.accessibilityValue?.max,
min: otherProps['aria-valuemin'] ?? otherProps.accessibilityValue?.min,
now: otherProps['aria-valuenow'] ?? otherProps.accessibilityValue?.now,
text: otherProps['aria-valuetext'] ?? otherProps.accessibilityValue?.text,
};
const restWithDefaultProps = {...otherProps, accessibilityValue};

const flattenedStyle = flattenStyle(style);
const newPointerEvents = flattenedStyle?.pointerEvents || pointerEvents;

return (
<TextAncestor.Provider value={false}>
<ViewNativeComponent
{...otherProps}
accessibilityLiveRegion={
ariaLive === 'off' ? 'none' : ariaLive ?? accessibilityLiveRegion
}
Expand All @@ -160,13 +167,14 @@ const View: React.AbstractComponent<
accessibilityElementsHidden={
ariaHidden ?? accessibilityElementsHidden
}
accessibilityLabelledBy={_accessibilityLabelledBy}
accessibilityValue={_accessibilityValue}
importantForAccessibility={
ariaHidden === true
? 'no-hide-descendants'
: importantForAccessibility
}
nativeID={id ?? nativeID}
{...restWithDefaultProps}
style={style}
pointerEvents={newPointerEvents}
ref={forwardedRef}
Expand Down
7 changes: 7 additions & 0 deletions Libraries/Components/View/ViewPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,13 @@ export type ViewProps = $ReadOnly<{|
*/
'aria-hidden'?: ?boolean,

/**
* It reperesents the nativeID of the associated label text. When the assistive technology focuses on the component with this props, the text is read aloud.
*
* @platform android
*/
'aria-labelledby'?: ?string,

/**
* 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
4 changes: 3 additions & 1 deletion Libraries/Image/Image.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,11 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => {
? loadingIndicatorSource.uri
: null,
ref: forwardedRef,
accessible: props.alt !== undefined ? true : props.accessible,
accessibilityLabel:
props['aria-label'] ?? props.accessibilityLabel ?? props.alt,
accessibilityLabelledBy:
props?.['aria-labelledby'] ?? props?.accessibilityLabelledBy,
accessible: props.alt !== undefined ? true : props.accessible,
accessibilityState: {
busy: props['aria-busy'] ?? props.accessibilityState?.busy,
checked: props['aria-checked'] ?? props.accessibilityState?.checked,
Expand Down
6 changes: 6 additions & 0 deletions Libraries/Image/ImageProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ export type ImageProps = {|
*/
'aria-label'?: ?Stringish,

/**
* Reperesents the nativeID of the associated label. When the assistive technology focuses on the component with this props.
*
* @platform android
*/
'aria-labelledby'?: ?string,
/**
* The text that's read by the screen reader when the user interacts with
* the image.
Expand Down
8 changes: 8 additions & 0 deletions Libraries/Text/TextProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ export type TextProps = $ReadOnly<{|
'aria-disabled'?: ?boolean,
'aria-expanded'?: ?boolean,
'aria-selected'?: ?boolean,

/**
* Reperesents the nativeID of the associated label text. When the assistive technology focuses on the component with this props, the text is read aloud.
*
* @platform android
*/
'aria-labelledby'?: ?string,

children?: ?Node,

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1446,4 +1446,18 @@ exports.examples = [
);
},
},
{
title: 'TextInput with aria-labelledby attribute"',
render(): React.Element<typeof View> {
return (
<View>
<Text nativeID="testAriaLabelledBy">Phone Number</Text>
<TextInput
aria-labelledby={'testAriaLabelledBy'}
style={styles.default}
/>
</View>
);
},
},
];

0 comments on commit 6c939c0

Please sign in to comment.