From 9b93788dd573ac5c29fc22560ad35ab19b460c3d Mon Sep 17 00:00:00 2001 From: ankit-tailor Date: Mon, 29 Aug 2022 13:03:43 +0530 Subject: [PATCH 01/21] feat: typing for accessibilit state alias --- Libraries/Components/View/ViewPropTypes.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index c7ee1baa63a16b..15a0554eb26c62 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -455,6 +455,12 @@ export type ViewProps = $ReadOnly<{| accessibilityState?: ?AccessibilityState, accessibilityValue?: ?AccessibilityValue, + 'aria-disabled'?: ?boolean, + 'aria-checked'?: ?boolean, + 'aria-disabled'?: ?boolean, + 'aria-expanded'?: ?boolean, + 'aria-selected'?: ?boolean, + /** * Provides an array of custom actions available for accessibility. * From 374ea185f9e216ef4cde336836f76ca6a93ac3ea Mon Sep 17 00:00:00 2001 From: ankit-tailor Date: Mon, 29 Aug 2022 13:04:04 +0530 Subject: [PATCH 02/21] feat: mapping for accssibility state alias --- Libraries/Components/View/View.js | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index 0379a7ce912f97..2e26b406afd8fc 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -27,9 +27,33 @@ const View: React.AbstractComponent< ViewProps, React.ElementRef, > = React.forwardRef((props: ViewProps, forwardedRef) => { + const { + 'aria-busy': ariaBusy, + 'aria-checked': ariaChecked, + 'aria-disabled': ariaDisabled, + 'aria-expanded': ariaExpanded, + 'aria-selected': ariaSelected, + accessibilityState, + ...restProps + } = props; + + const _accessibilityState = { + busy: ariaBusy ?? accessibilityState?.busy, + checked: ariaChecked ?? accessibilityState?.checked, + disabled: ariaDisabled ?? accessibilityState?.disabled, + expanded: ariaExpanded ?? accessibilityState?.expanded, + selected: ariaSelected ?? accessibilityState?.selected, + }; + + console.log(_accessibilityState, '@@'); + return ( - + ); }); From b65c50dca520c0d84fff299eaa772998a7662c75 Mon Sep 17 00:00:00 2001 From: ankit-tailor Date: Mon, 29 Aug 2022 13:22:08 +0530 Subject: [PATCH 03/21] fix: add aria-busy --- Libraries/Components/View/ViewPropTypes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index 15a0554eb26c62..e8aba6bc2cd80b 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -457,7 +457,7 @@ export type ViewProps = $ReadOnly<{| 'aria-disabled'?: ?boolean, 'aria-checked'?: ?boolean, - 'aria-disabled'?: ?boolean, + 'aria-busy'?: ?boolean, 'aria-expanded'?: ?boolean, 'aria-selected'?: ?boolean, From 3adb318a3797bf43d874b4c6ec341fafc38e2e86 Mon Sep 17 00:00:00 2001 From: ankit-tailor Date: Mon, 29 Aug 2022 13:25:30 +0530 Subject: [PATCH 04/21] fix: remove log --- Libraries/Components/View/View.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index 2e26b406afd8fc..4db63c0c1e58f6 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -45,8 +45,6 @@ const View: React.AbstractComponent< selected: ariaSelected ?? accessibilityState?.selected, }; - console.log(_accessibilityState, '@@'); - return ( Date: Mon, 29 Aug 2022 21:47:13 +0530 Subject: [PATCH 05/21] feat: accessibility state typings for pressable --- Libraries/Components/Pressable/Pressable.js | 27 +++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/Libraries/Components/Pressable/Pressable.js b/Libraries/Components/Pressable/Pressable.js index aab4f21d33ed89..557dcbc91bd75a 100644 --- a/Libraries/Components/Pressable/Pressable.js +++ b/Libraries/Components/Pressable/Pressable.js @@ -49,6 +49,11 @@ type Props = $ReadOnly<{| accessibilityLiveRegion?: ?('none' | 'polite' | 'assertive'), accessibilityRole?: ?AccessibilityRole, accessibilityState?: ?AccessibilityState, + 'aria-disabled'?: ?boolean, + 'aria-checked'?: ?boolean, + 'aria-busy'?: ?boolean, + 'aria-expanded'?: ?boolean, + 'aria-selected'?: ?boolean, accessibilityValue?: ?AccessibilityValue, accessibilityViewIsModal?: ?boolean, accessible?: ?boolean, @@ -175,6 +180,12 @@ type Props = $ReadOnly<{| function Pressable(props: Props, forwardedRef): React.Node { const { accessible, + 'aria-busy': ariaBusy, + 'aria-checked': ariaChecked, + 'aria-disabled': ariaDisabled, + 'aria-expanded': ariaExpanded, + 'aria-selected': ariaSelected, + accessibilityState, android_disableSound, android_ripple, cancelable, @@ -205,16 +216,22 @@ function Pressable(props: Props, forwardedRef): React.Node { const [pressed, setPressed] = usePressState(testOnly_pressed === true); - const accessibilityState = - disabled != null - ? {...props.accessibilityState, disabled} - : props.accessibilityState; + let _accessibilityState = { + busy: ariaBusy ?? accessibilityState?.busy, + checked: ariaChecked ?? accessibilityState?.checked, + disabled: ariaDisabled ?? accessibilityState?.disabled, + expanded: ariaExpanded ?? accessibilityState?.expanded, + selected: ariaSelected ?? accessibilityState?.selected, + }; + + _accessibilityState = + disabled != null ? {..._accessibilityState, disabled} : _accessibilityState; const restPropsWithDefaults: React.ElementConfig = { ...restProps, ...android_rippleConfig?.viewProps, accessible: accessible !== false, - accessibilityState, + accessibilityState: _accessibilityState, focusable: focusable !== false, hitSlop, }; From 5686e1eb294e41c21ae3ba4cfa01250e2e44aca6 Mon Sep 17 00:00:00 2001 From: ankit-tailor Date: Mon, 29 Aug 2022 22:16:26 +0530 Subject: [PATCH 06/21] feat: accessibility state alias for text --- Libraries/Text/Text.js | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 57b6a2ea82ca28..a92be4fa295284 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -32,6 +32,12 @@ const Text: React.AbstractComponent< > = React.forwardRef((props: TextProps, forwardedRef) => { const { accessible, + 'aria-busy': ariaBusy, + 'aria-checked': ariaChecked, + 'aria-disabled': ariaDisabled, + 'aria-expanded': ariaExpanded, + 'aria-selected': ariaSelected, + accessibilityState, allowFontScaling, ellipsizeMode, onLongPress, @@ -51,14 +57,23 @@ const Text: React.AbstractComponent< const [isHighlighted, setHighlighted] = useState(false); + const _accessibilityState = { + busy: ariaBusy ?? accessibilityState?.busy, + checked: ariaChecked ?? accessibilityState?.checked, + disabled: ariaDisabled ?? accessibilityState?.disabled, + expanded: ariaExpanded ?? accessibilityState?.expanded, + selected: ariaSelected ?? accessibilityState?.selected, + }; + const _disabled = restProps.disabled != null ? restProps.disabled - : props.accessibilityState?.disabled; - const _accessibilityState = - _disabled !== props.accessibilityState?.disabled - ? {...props.accessibilityState, disabled: _disabled} - : props.accessibilityState; + : _accessibilityState?.disabled; + + const nativeTextAccessibilityState = + _disabled !== _accessibilityState?.disabled + ? {..._accessibilityState, disabled: _disabled} + : _accessibilityState; const isPressable = (onPress != null || @@ -178,6 +193,7 @@ const Text: React.AbstractComponent< return hasTextAncestor ? ( Date: Mon, 29 Aug 2022 22:17:04 +0530 Subject: [PATCH 07/21] feat: accessibility state alias typing for text --- Libraries/Text/TextProps.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Libraries/Text/TextProps.js b/Libraries/Text/TextProps.js index 84556c43b50046..52acd16c1277aa 100644 --- a/Libraries/Text/TextProps.js +++ b/Libraries/Text/TextProps.js @@ -57,6 +57,11 @@ export type TextProps = $ReadOnly<{| accessibilityLabel?: ?Stringish, accessibilityRole?: ?AccessibilityRole, accessibilityState?: ?AccessibilityState, + 'aria-disabled'?: ?boolean, + 'aria-checked'?: ?boolean, + 'aria-busy'?: ?boolean, + 'aria-expanded'?: ?boolean, + 'aria-selected'?: ?boolean, /** * Whether font should be scaled down automatically. From e58b762c58c4740fa202c32c0d31c4cf9429f61c Mon Sep 17 00:00:00 2001 From: ankit-tailor Date: Tue, 30 Aug 2022 11:56:34 +0530 Subject: [PATCH 08/21] fix: remove undefined keys --- Libraries/Components/Pressable/Pressable.js | 10 ++++++++++ Libraries/Components/View/View.js | 10 ++++++++++ Libraries/Text/Text.js | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/Libraries/Components/Pressable/Pressable.js b/Libraries/Components/Pressable/Pressable.js index 557dcbc91bd75a..367fb155e269a5 100644 --- a/Libraries/Components/Pressable/Pressable.js +++ b/Libraries/Components/Pressable/Pressable.js @@ -224,6 +224,16 @@ function Pressable(props: Props, forwardedRef): React.Node { selected: ariaSelected ?? accessibilityState?.selected, }; + /** + * Removing undefined keys from _accessibilityState + */ + + Object.keys(_accessibilityState).forEach(key => { + if (_accessibilityState[key] === undefined) { + delete _accessibilityState[key]; + } + }); + _accessibilityState = disabled != null ? {..._accessibilityState, disabled} : _accessibilityState; diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index 4db63c0c1e58f6..8f3e3d6ae54bb3 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -45,6 +45,16 @@ const View: React.AbstractComponent< selected: ariaSelected ?? accessibilityState?.selected, }; + /** + * Removing undefined keys from _accessibilityState + */ + + Object.keys(_accessibilityState).forEach(key => { + if (_accessibilityState[key] === undefined) { + delete _accessibilityState[key]; + } + }); + return ( { + if (_accessibilityState[key] === undefined) { + delete _accessibilityState[key]; + } + }); + const _disabled = restProps.disabled != null ? restProps.disabled From 1ab9b3ba735d9f47ceb88e824ca8e7f76ba7487f Mon Sep 17 00:00:00 2001 From: ankit-tailor Date: Tue, 30 Aug 2022 15:03:06 +0530 Subject: [PATCH 09/21] fix: alpha sorted props --- Libraries/Components/Pressable/Pressable.js | 27 ++++++++++++++------- Libraries/Components/View/View.js | 8 ++++-- Libraries/Components/View/ViewPropTypes.js | 17 ++++++++----- Libraries/Text/Text.js | 9 ++++--- Libraries/Text/TextProps.js | 16 ++++++++---- 5 files changed, 52 insertions(+), 25 deletions(-) diff --git a/Libraries/Components/Pressable/Pressable.js b/Libraries/Components/Pressable/Pressable.js index 367fb155e269a5..e9723b547242e1 100644 --- a/Libraries/Components/Pressable/Pressable.js +++ b/Libraries/Components/Pressable/Pressable.js @@ -49,14 +49,20 @@ type Props = $ReadOnly<{| accessibilityLiveRegion?: ?('none' | 'polite' | 'assertive'), accessibilityRole?: ?AccessibilityRole, accessibilityState?: ?AccessibilityState, - 'aria-disabled'?: ?boolean, - 'aria-checked'?: ?boolean, - 'aria-busy'?: ?boolean, - 'aria-expanded'?: ?boolean, - 'aria-selected'?: ?boolean, accessibilityValue?: ?AccessibilityValue, accessibilityViewIsModal?: ?boolean, accessible?: ?boolean, + + /** + * alias for accessibilityState + * + * see https://reactnative.dev/docs/accessibility#accessibilitystate + */ + 'aria-busy'?: ?boolean, + 'aria-checked'?: ?boolean, + 'aria-disabled'?: ?boolean, + 'aria-expanded'?: ?boolean, + 'aria-selected'?: ?boolean, focusable?: ?boolean, importantForAccessibility?: ?('auto' | 'yes' | 'no' | 'no-hide-descendants'), onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed, @@ -179,15 +185,15 @@ type Props = $ReadOnly<{| * LTI update could not be added via codemod */ function Pressable(props: Props, forwardedRef): React.Node { const { + accessibilityState, + android_disableSound, + android_ripple, accessible, 'aria-busy': ariaBusy, 'aria-checked': ariaChecked, 'aria-disabled': ariaDisabled, 'aria-expanded': ariaExpanded, 'aria-selected': ariaSelected, - accessibilityState, - android_disableSound, - android_ripple, cancelable, children, delayHoverIn, @@ -241,11 +247,14 @@ function Pressable(props: Props, forwardedRef): React.Node { ...restProps, ...android_rippleConfig?.viewProps, accessible: accessible !== false, - accessibilityState: _accessibilityState, focusable: focusable !== false, hitSlop, }; + if (Object.keys(_accessibilityState).length !== 0) { + restPropsWithDefaults['accessibilityState'] = _accessibilityState; + } + const config = useMemo( () => ({ cancelable, diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index c47d045d971f42..8f7767613d01ea 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -29,12 +29,12 @@ const View: React.AbstractComponent< > = React.forwardRef( ({tabIndex, focusable, ...otherProps}: ViewProps, forwardedRef) => { const { + accessibilityState, 'aria-busy': ariaBusy, 'aria-checked': ariaChecked, 'aria-disabled': ariaDisabled, 'aria-expanded': ariaExpanded, 'aria-selected': ariaSelected, - accessibilityState, ...restProps } = otherProps; @@ -55,10 +55,14 @@ const View: React.AbstractComponent< delete _accessibilityState[key]; } }); + + if (Object.keys(_accessibilityState).length !== 0) { + restProps['accessibilityState'] = _accessibilityState; + } + return ( , + /** + * alias for accessibilityState + * + * see https://reactnative.dev/docs/accessibility#accessibilitystate + */ + 'aria-busy'?: ?boolean, + 'aria-checked'?: ?boolean, + 'aria-disabled'?: ?boolean, + 'aria-expanded'?: ?boolean, + 'aria-selected'?: ?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 diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 11a5d528174df0..8f6dce09a2da7a 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -32,13 +32,13 @@ const Text: React.AbstractComponent< > = React.forwardRef((props: TextProps, forwardedRef) => { const { accessible, + accessibilityState, + allowFontScaling, 'aria-busy': ariaBusy, 'aria-checked': ariaChecked, 'aria-disabled': ariaDisabled, 'aria-expanded': ariaExpanded, 'aria-selected': ariaSelected, - accessibilityState, - allowFontScaling, ellipsizeMode, onLongPress, onPress, @@ -201,9 +201,12 @@ const Text: React.AbstractComponent< default: accessible, }); + if (Object.keys(_accessibilityState).length !== 0) { + restProps['accessibilityState'] = _accessibilityState; + } + return hasTextAncestor ? ( Date: Tue, 30 Aug 2022 17:26:17 +0530 Subject: [PATCH 10/21] fix: object dot notation --- Libraries/Components/Pressable/Pressable.js | 7 +++++-- Libraries/Components/View/View.js | 20 ++++++++++++-------- Libraries/Text/Text.js | 19 ++++++++++--------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/Libraries/Components/Pressable/Pressable.js b/Libraries/Components/Pressable/Pressable.js index e9723b547242e1..1ebed43450379c 100644 --- a/Libraries/Components/Pressable/Pressable.js +++ b/Libraries/Components/Pressable/Pressable.js @@ -243,7 +243,7 @@ function Pressable(props: Props, forwardedRef): React.Node { _accessibilityState = disabled != null ? {..._accessibilityState, disabled} : _accessibilityState; - const restPropsWithDefaults: React.ElementConfig = { + let restPropsWithDefaults: React.ElementConfig = { ...restProps, ...android_rippleConfig?.viewProps, accessible: accessible !== false, @@ -252,7 +252,10 @@ function Pressable(props: Props, forwardedRef): React.Node { }; if (Object.keys(_accessibilityState).length !== 0) { - restPropsWithDefaults['accessibilityState'] = _accessibilityState; + restPropsWithDefaults = { + ...restPropsWithDefaults, + accessibilityState: _accessibilityState, + }; } const config = useMemo( diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index 8f7767613d01ea..656f2b854dd132 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -29,7 +29,6 @@ const View: React.AbstractComponent< > = React.forwardRef( ({tabIndex, focusable, ...otherProps}: ViewProps, forwardedRef) => { const { - accessibilityState, 'aria-busy': ariaBusy, 'aria-checked': ariaChecked, 'aria-disabled': ariaDisabled, @@ -39,11 +38,11 @@ const View: React.AbstractComponent< } = otherProps; const _accessibilityState = { - busy: ariaBusy ?? accessibilityState?.busy, - checked: ariaChecked ?? accessibilityState?.checked, - disabled: ariaDisabled ?? accessibilityState?.disabled, - expanded: ariaExpanded ?? accessibilityState?.expanded, - selected: ariaSelected ?? accessibilityState?.selected, + busy: ariaBusy ?? otherProps.accessibilityState?.busy, + checked: ariaChecked ?? otherProps.accessibilityState?.checked, + disabled: ariaDisabled ?? otherProps.accessibilityState?.disabled, + expanded: ariaExpanded ?? otherProps.accessibilityState?.expanded, + selected: ariaSelected ?? otherProps.accessibilityState?.selected, }; /** @@ -56,15 +55,20 @@ const View: React.AbstractComponent< } }); + let restWithDefaultProps = {...restProps}; + if (Object.keys(_accessibilityState).length !== 0) { - restProps['accessibilityState'] = _accessibilityState; + restWithDefaultProps = { + ...restWithDefaultProps, + accessibilityState: _accessibilityState, + }; } return ( diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 8f6dce09a2da7a..569ebf5e91201c 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -32,7 +32,6 @@ const Text: React.AbstractComponent< > = React.forwardRef((props: TextProps, forwardedRef) => { const { accessible, - accessibilityState, allowFontScaling, 'aria-busy': ariaBusy, 'aria-checked': ariaChecked, @@ -58,11 +57,11 @@ const Text: React.AbstractComponent< const [isHighlighted, setHighlighted] = useState(false); const _accessibilityState = { - busy: ariaBusy ?? accessibilityState?.busy, - checked: ariaChecked ?? accessibilityState?.checked, - disabled: ariaDisabled ?? accessibilityState?.disabled, - expanded: ariaExpanded ?? accessibilityState?.expanded, - selected: ariaSelected ?? accessibilityState?.selected, + busy: ariaBusy ?? props.accessibilityState?.busy, + checked: ariaChecked ?? props.accessibilityState?.checked, + disabled: ariaDisabled ?? props.accessibilityState?.disabled, + expanded: ariaExpanded ?? props.accessibilityState?.expanded, + selected: ariaSelected ?? props.accessibilityState?.selected, }; /** @@ -201,13 +200,15 @@ const Text: React.AbstractComponent< default: accessible, }); + let restWithDefaultProps = {...restProps}; + if (Object.keys(_accessibilityState).length !== 0) { - restProps['accessibilityState'] = _accessibilityState; + restWithDefaultProps.accessibilityState = _accessibilityState; } return hasTextAncestor ? ( Date: Thu, 1 Sep 2022 00:21:27 +0530 Subject: [PATCH 11/21] feat: alias for accessibilit state --- .../Components/Touchable/TouchableOpacity.js | 25 ++++++++++--- .../Touchable/TouchableWithoutFeedback.js | 37 ++++++++++++++++--- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/Libraries/Components/Touchable/TouchableOpacity.js b/Libraries/Components/Touchable/TouchableOpacity.js index 67e18c06d54c83..d5a500d498db69 100644 --- a/Libraries/Components/Touchable/TouchableOpacity.js +++ b/Libraries/Components/Touchable/TouchableOpacity.js @@ -137,7 +137,10 @@ class TouchableOpacity extends React.Component { _createPressabilityConfig(): PressabilityConfig { return { cancelable: !this.props.rejectResponderTermination, - disabled: this.props.disabled ?? this.props.accessibilityState?.disabled, + disabled: + this.props.disabled ?? + this.props['aria-disabled'] ?? + this.props.accessibilityState?.disabled, hitSlop: this.props.hitSlop, delayLongPress: this.props.delayLongPress, delayPressIn: this.props.delayPressIn, @@ -212,13 +215,25 @@ class TouchableOpacity extends React.Component { const {onBlur, onFocus, ...eventHandlersWithoutBlurAndFocus} = this.state.pressability.getEventHandlers(); - const accessibilityState = + let _accessibilityState = { + busy: this.props['aria-busy'] ?? this.props.accessibilityState?.busy, + checked: + this.props['aria-checked'] ?? this.props.accessibilityState?.checked, + disabled: + this.props['aria-disabled'] ?? this.props.accessibilityState?.disabled, + expanded: + this.props['aria-expanded'] ?? this.props.accessibilityState?.expanded, + selected: + this.props['aria-selected'] ?? this.props.accessibilityState?.selected, + }; + + _accessibilityState = this.props.disabled != null ? { - ...this.props.accessibilityState, + ..._accessibilityState, disabled: this.props.disabled, } - : this.props.accessibilityState; + : _accessibilityState; return ( { accessibilityHint={this.props.accessibilityHint} accessibilityLanguage={this.props.accessibilityLanguage} accessibilityRole={this.props.accessibilityRole} - accessibilityState={accessibilityState} + accessibilityState={_accessibilityState} accessibilityActions={this.props.accessibilityActions} onAccessibilityAction={this.props.onAccessibilityAction} accessibilityValue={this.props.accessibilityValue} diff --git a/Libraries/Components/Touchable/TouchableWithoutFeedback.js b/Libraries/Components/Touchable/TouchableWithoutFeedback.js index 2b3bd4b930e14b..c9f0ae34a05df3 100755 --- a/Libraries/Components/Touchable/TouchableWithoutFeedback.js +++ b/Libraries/Components/Touchable/TouchableWithoutFeedback.js @@ -42,6 +42,16 @@ type Props = $ReadOnly<{| accessibilityValue?: ?AccessibilityValue, accessibilityViewIsModal?: ?boolean, accessible?: ?boolean, + /** + * alias for accessibilityState + * + * see https://reactnative.dev/docs/accessibility#accessibilitystate + */ + 'aria-busy'?: ?boolean, + 'aria-checked'?: ?boolean, + 'aria-disabled'?: ?boolean, + 'aria-expanded'?: ?boolean, + 'aria-selected'?: ?boolean, children?: ?React.Node, delayLongPress?: ?number, delayPressIn?: ?number, @@ -106,6 +116,18 @@ class TouchableWithoutFeedback extends React.Component { } } + let _accessibilityState = { + busy: this.props['aria-busy'] ?? this.props.accessibilityState?.busy, + checked: + this.props['aria-checked'] ?? this.props.accessibilityState?.checked, + disabled: + this.props['aria-disabled'] ?? this.props.accessibilityState?.disabled, + expanded: + this.props['aria-expanded'] ?? this.props.accessibilityState?.expanded, + selected: + this.props['aria-selected'] ?? this.props.accessibilityState?.selected, + }; + // BACKWARD-COMPATIBILITY: Focus and blur events were never supported before // adopting `Pressability`, so preserve that behavior. const {onBlur, onFocus, ...eventHandlersWithoutBlurAndFocus} = @@ -117,10 +139,10 @@ class TouchableWithoutFeedback extends React.Component { accessibilityState: this.props.disabled != null ? { - ...this.props.accessibilityState, + ..._accessibilityState, disabled: this.props.disabled, } - : this.props.accessibilityState, + : _accessibilityState, focusable: this.props.focusable !== false && this.props.onPress !== undefined, }; @@ -142,13 +164,16 @@ class TouchableWithoutFeedback extends React.Component { } } -function createPressabilityConfig(props: Props): PressabilityConfig { +function createPressabilityConfig({ + 'aria-disabled': ariaDisabled, + ...props +}: Props): PressabilityConfig { + const accessibilityStateDisabled = + ariaDisabled ?? props.accessibilityState?.disabled; return { cancelable: !props.rejectResponderTermination, disabled: - props.disabled !== null - ? props.disabled - : props.accessibilityState?.disabled, + props.disabled !== null ? props.disabled : accessibilityStateDisabled, hitSlop: props.hitSlop, delayLongPress: props.delayLongPress, delayPressIn: props.delayPressIn, From 2bd848f670c6d5184772d9058ef96bb6d49bc746 Mon Sep 17 00:00:00 2001 From: ankit-tailor Date: Thu, 1 Sep 2022 00:39:07 +0530 Subject: [PATCH 12/21] feat: alias for accessibilit state --- .../Components/Touchable/TouchableBounce.js | 14 ++++++++++- .../Touchable/TouchableNativeFeedback.js | 24 +++++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/Libraries/Components/Touchable/TouchableBounce.js b/Libraries/Components/Touchable/TouchableBounce.js index f77ab0f5738fcf..e2b97be1381cb6 100644 --- a/Libraries/Components/Touchable/TouchableBounce.js +++ b/Libraries/Components/Touchable/TouchableBounce.js @@ -131,6 +131,18 @@ class TouchableBounce extends React.Component { const {onBlur, onFocus, ...eventHandlersWithoutBlurAndFocus} = this.state.pressability.getEventHandlers(); + let _accessibilityState = { + busy: this.props['aria-busy'] ?? this.props.accessibilityState?.busy, + checked: + this.props['aria-checked'] ?? this.props.accessibilityState?.checked, + disabled: + this.props['aria-disabled'] ?? this.props.accessibilityState?.disabled, + expanded: + this.props['aria-expanded'] ?? this.props.accessibilityState?.expanded, + selected: + this.props['aria-selected'] ?? this.props.accessibilityState?.selected, + }; + return ( { accessibilityHint={this.props.accessibilityHint} accessibilityLanguage={this.props.accessibilityLanguage} accessibilityRole={this.props.accessibilityRole} - accessibilityState={this.props.accessibilityState} + accessibilityState={_accessibilityState} accessibilityActions={this.props.accessibilityActions} onAccessibilityAction={this.props.onAccessibilityAction} accessibilityValue={this.props.accessibilityValue} diff --git a/Libraries/Components/Touchable/TouchableNativeFeedback.js b/Libraries/Components/Touchable/TouchableNativeFeedback.js index 8fff2f302397f2..18726751f96d79 100644 --- a/Libraries/Components/Touchable/TouchableNativeFeedback.js +++ b/Libraries/Components/Touchable/TouchableNativeFeedback.js @@ -162,12 +162,14 @@ class TouchableNativeFeedback extends React.Component { }; _createPressabilityConfig(): PressabilityConfig { + const accessibilityStateDisabled = + this.props['aria-disabled'] ?? this.props.accessibilityState?.disabled; return { cancelable: !this.props.rejectResponderTermination, disabled: this.props.disabled != null ? this.props.disabled - : this.props.accessibilityState?.disabled, + : accessibilityStateDisabled, hitSlop: this.props.hitSlop, delayLongPress: this.props.delayLongPress, delayPressIn: this.props.delayPressIn, @@ -251,13 +253,25 @@ class TouchableNativeFeedback extends React.Component { const {onBlur, onFocus, ...eventHandlersWithoutBlurAndFocus} = this.state.pressability.getEventHandlers(); - const accessibilityState = + let _accessibilityState = { + busy: this.props['aria-busy'] ?? this.props.accessibilityState?.busy, + checked: + this.props['aria-checked'] ?? this.props.accessibilityState?.checked, + disabled: + this.props['aria-disabled'] ?? this.props.accessibilityState?.disabled, + expanded: + this.props['aria-expanded'] ?? this.props.accessibilityState?.expanded, + selected: + this.props['aria-selected'] ?? this.props.accessibilityState?.selected, + }; + + _accessibilityState = this.props.disabled != null ? { - ...this.props.accessibilityState, + ..._accessibilityState, disabled: this.props.disabled, } - : this.props.accessibilityState; + : _accessibilityState; return React.cloneElement( element, @@ -274,7 +288,7 @@ class TouchableNativeFeedback extends React.Component { accessibilityLanguage: this.props.accessibilityLanguage, accessibilityLabel: this.props.accessibilityLabel, accessibilityRole: this.props.accessibilityRole, - accessibilityState: accessibilityState, + accessibilityState: _accessibilityState, accessibilityActions: this.props.accessibilityActions, onAccessibilityAction: this.props.onAccessibilityAction, accessibilityValue: this.props.accessibilityValue, From c5ea82d7d04ced06941e56fa501fb0f0f08789af Mon Sep 17 00:00:00 2001 From: ankit-tailor Date: Thu, 1 Sep 2022 01:13:27 +0530 Subject: [PATCH 13/21] feat: alias accessibility state for TextInput --- Libraries/Components/TextInput/TextInput.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 5e1384a77c57ee..3e6c37ae087aa0 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -1312,6 +1312,14 @@ function InternalTextInput(props: Props): React.Node { // so omitting onBlur and onFocus pressability handlers here. const {onBlur, onFocus, ...eventHandlers} = usePressability(config) || {}; + const _accessibilityState = { + busy: props['aria-busy'] ?? props.accessibilityState?.busy, + checked: props['aria-checked'] ?? props.accessibilityState?.checked, + disabled: props['aria-disabled'] ?? props.accessibilityState?.disabled, + expanded: props['aria-expanded'] ?? props.accessibilityState?.expanded, + selected: props['aria-selected'] ?? props.accessibilityState?.selected, + }; + if (Platform.OS === 'ios') { const RCTTextInputView = props.multiline === true @@ -1333,6 +1341,7 @@ function InternalTextInput(props: Props): React.Node { {...props} {...eventHandlers} accessible={accessible} + accessibilityState={_accessibilityState} submitBehavior={submitBehavior} caretHidden={caretHidden} dataDetectorTypes={props.dataDetectorTypes} @@ -1380,6 +1389,7 @@ function InternalTextInput(props: Props): React.Node { {...props} {...eventHandlers} accessible={accessible} + accessibilityState={_accessibilityState} autoCapitalize={autoCapitalize} submitBehavior={submitBehavior} caretHidden={caretHidden} From 73778b5e95333b67d575d327ad438cf98a2752e4 Mon Sep 17 00:00:00 2001 From: ankit-tailor Date: Thu, 1 Sep 2022 01:47:12 +0530 Subject: [PATCH 14/21] feat: accessibility state alias --- Libraries/Components/Button.js | 37 ++++++++++++++++++++++++++------ Libraries/Image/Image.android.js | 7 ++++++ Libraries/Image/Image.ios.js | 9 ++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/Libraries/Components/Button.js b/Libraries/Components/Button.js index d396acebf5e59f..b2bf05b5914c39 100644 --- a/Libraries/Components/Button.js +++ b/Libraries/Components/Button.js @@ -147,6 +147,17 @@ type ButtonProps = $ReadOnly<{| onAccessibilityAction?: ?(event: AccessibilityActionEvent) => mixed, accessibilityState?: ?AccessibilityState, + /** + * alias for accessibilityState + * + * see https://reactnative.dev/docs/accessibility#accessibilitystate + */ + 'aria-busy'?: ?boolean, + 'aria-checked'?: ?boolean, + 'aria-disabled'?: ?boolean, + 'aria-expanded'?: ?boolean, + 'aria-selected'?: ?boolean, + /** * [Android] Controlling if a view fires accessibility events and if it is reported to accessibility services. */ @@ -270,6 +281,12 @@ class Button extends React.Component { render(): React.Node { const { accessibilityLabel, + accessibilityState, + 'aria-busy': ariaBusy, + 'aria-checked': ariaChecked, + 'aria-disabled': ariaDisabled, + 'aria-expanded': ariaExpanded, + 'aria-selected': ariaSelected, importantForAccessibility, color, onPress, @@ -298,15 +315,23 @@ class Button extends React.Component { } } + let _accessibilityState = { + busy: ariaBusy ?? accessibilityState?.busy, + checked: ariaChecked ?? accessibilityState?.checked, + disabled: ariaDisabled ?? accessibilityState?.disabled, + expanded: ariaExpanded ?? accessibilityState?.expanded, + selected: ariaSelected ?? accessibilityState?.selected, + }; + const disabled = this.props.disabled != null ? this.props.disabled - : this.props.accessibilityState?.disabled; + : _accessibilityState?.disabled; - const accessibilityState = - disabled !== this.props.accessibilityState?.disabled - ? {...this.props.accessibilityState, disabled} - : this.props.accessibilityState; + _accessibilityState = + disabled !== _accessibilityState?.disabled + ? {..._accessibilityState, disabled} + : _accessibilityState; if (disabled) { buttonStyles.push(styles.buttonDisabled); @@ -337,7 +362,7 @@ class Button extends React.Component { accessibilityHint={accessibilityHint} accessibilityLanguage={accessibilityLanguage} accessibilityRole="button" - accessibilityState={accessibilityState} + accessibilityState={_accessibilityState} importantForAccessibility={_importantForAccessibility} hasTVPreferredFocus={hasTVPreferredFocus} nextFocusDown={nextFocusDown} diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index eac8a56c63eba7..2e16715ec41764 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -186,6 +186,13 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => { ? loadingIndicatorSource.uri : null, ref: forwardedRef, + accessibilityState: { + busy: props['aria-busy'] ?? props.accessibilityState?.busy, + checked: props['aria-checked'] ?? props.accessibilityState?.checked, + disabled: props['aria-disabled'] ?? props.accessibilityState?.disabled, + expanded: props['aria-expanded'] ?? props.accessibilityState?.expanded, + selected: props['aria-selected'] ?? props.accessibilityState?.selected, + }, }; return ( diff --git a/Libraries/Image/Image.ios.js b/Libraries/Image/Image.ios.js index f4c5ca3ca421a5..46902243cd60f1 100644 --- a/Libraries/Image/Image.ios.js +++ b/Libraries/Image/Image.ios.js @@ -143,12 +143,21 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => { ); } + const _accessibilityState = { + busy: props['aria-busy'] ?? props.accessibilityState?.busy, + checked: props['aria-checked'] ?? props.accessibilityState?.checked, + disabled: props['aria-disabled'] ?? props.accessibilityState?.disabled, + expanded: props['aria-expanded'] ?? props.accessibilityState?.expanded, + selected: props['aria-selected'] ?? props.accessibilityState?.selected, + }; + return ( {analyticTag => { return ( Date: Thu, 1 Sep 2022 02:17:31 +0530 Subject: [PATCH 15/21] fix: remove undefined key logic --- Libraries/Components/Pressable/Pressable.js | 10 ------- Libraries/Components/View/View.js | 33 +++++---------------- Libraries/Text/Text.js | 10 ------- 3 files changed, 8 insertions(+), 45 deletions(-) diff --git a/Libraries/Components/Pressable/Pressable.js b/Libraries/Components/Pressable/Pressable.js index 1ebed43450379c..46a4069d530dc2 100644 --- a/Libraries/Components/Pressable/Pressable.js +++ b/Libraries/Components/Pressable/Pressable.js @@ -230,16 +230,6 @@ function Pressable(props: Props, forwardedRef): React.Node { selected: ariaSelected ?? accessibilityState?.selected, }; - /** - * Removing undefined keys from _accessibilityState - */ - - Object.keys(_accessibilityState).forEach(key => { - if (_accessibilityState[key] === undefined) { - delete _accessibilityState[key]; - } - }); - _accessibilityState = disabled != null ? {..._accessibilityState, disabled} : _accessibilityState; diff --git a/Libraries/Components/View/View.js b/Libraries/Components/View/View.js index 656f2b854dd132..b35062c8803209 100644 --- a/Libraries/Components/View/View.js +++ b/Libraries/Components/View/View.js @@ -29,6 +29,7 @@ const View: React.AbstractComponent< > = React.forwardRef( ({tabIndex, focusable, ...otherProps}: ViewProps, forwardedRef) => { const { + accessibilityState, 'aria-busy': ariaBusy, 'aria-checked': ariaChecked, 'aria-disabled': ariaDisabled, @@ -38,37 +39,19 @@ const View: React.AbstractComponent< } = otherProps; const _accessibilityState = { - busy: ariaBusy ?? otherProps.accessibilityState?.busy, - checked: ariaChecked ?? otherProps.accessibilityState?.checked, - disabled: ariaDisabled ?? otherProps.accessibilityState?.disabled, - expanded: ariaExpanded ?? otherProps.accessibilityState?.expanded, - selected: ariaSelected ?? otherProps.accessibilityState?.selected, + busy: ariaBusy ?? accessibilityState?.busy, + checked: ariaChecked ?? accessibilityState?.checked, + disabled: ariaDisabled ?? accessibilityState?.disabled, + expanded: ariaExpanded ?? accessibilityState?.expanded, + selected: ariaSelected ?? accessibilityState?.selected, }; - /** - * Removing undefined keys from _accessibilityState - */ - - Object.keys(_accessibilityState).forEach(key => { - if (_accessibilityState[key] === undefined) { - delete _accessibilityState[key]; - } - }); - - let restWithDefaultProps = {...restProps}; - - if (Object.keys(_accessibilityState).length !== 0) { - restWithDefaultProps = { - ...restWithDefaultProps, - accessibilityState: _accessibilityState, - }; - } - return ( diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 569ebf5e91201c..099536d851f6a5 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -64,16 +64,6 @@ const Text: React.AbstractComponent< selected: ariaSelected ?? props.accessibilityState?.selected, }; - /** - * Removing undefined keys from _accessibilityState - */ - - Object.keys(_accessibilityState).forEach(key => { - if (_accessibilityState[key] === undefined) { - delete _accessibilityState[key]; - } - }); - const _disabled = restProps.disabled != null ? restProps.disabled From 2848bf57810fe7f289387a0f7de7c8f9660ea2e3 Mon Sep 17 00:00:00 2001 From: ankit-tailor Date: Thu, 1 Sep 2022 02:18:15 +0530 Subject: [PATCH 16/21] feat: update snapshot --- .../__snapshots__/Pressable-test.js.snap | 48 +++++++++++++ .../__snapshots__/TextInput-test.js.snap | 18 +++++ .../TouchableNativeFeedback-test.js.snap | 67 ++++++++++++++----- .../TouchableOpacity-test.js.snap | 17 +++++ .../TouchableWithoutFeedback-test.js.snap | 28 ++++++++ .../__snapshots__/Button-test.js.snap | 51 ++++++++++++++ .../__snapshots__/Image-test.js.snap | 9 +++ 7 files changed, 223 insertions(+), 15 deletions(-) diff --git a/Libraries/Components/Pressable/__tests__/__snapshots__/Pressable-test.js.snap b/Libraries/Components/Pressable/__tests__/__snapshots__/Pressable-test.js.snap index 821d4f41ea56e5..4e03820efa8ea3 100644 --- a/Libraries/Components/Pressable/__tests__/__snapshots__/Pressable-test.js.snap +++ b/Libraries/Components/Pressable/__tests__/__snapshots__/Pressable-test.js.snap @@ -2,6 +2,15 @@ exports[` should render as expected: should deep render when mocked (please verify output manually) 1`] = ` should render as expected: should deep render when mocked exports[` should render as expected: should deep render when not mocked (please verify output manually) 1`] = ` should be disabled when disabled is true: should be disabled when disabled is true: should be disable should be disable shou shou sh sh should render as expected 1`] = ` + - Touchable - +/> `; -exports[` should render as expected 1`] = ` +exports[` should overwrite accessibilityState with value of disabled prop 1`] = ` should render as expected 1`] = ` /> `; -exports[` should be disabled when disabled is true 1`] = ` +exports[` should be disabled when disabled is true and accessibilityState is empty 1`] = ` should be disabled when disab /> `; -exports[` should be disabled when disabled is true and accessibilityState is empty 1`] = ` +exports[` should keep accessibilityState when disabled is true 1`] = ` shoul /> `; -exports[` should keep accessibilityState when disabled is true 1`] = ` +exports[` should overwrite accessibilityState with value of disabled prop 1`] = ` `; -exports[` should overwrite accessibilityState with value of disabled prop 1`] = ` +exports[` should be disabled when disabled is true 1`] = ` `; -exports[` should overwrite accessibilityState with value of disabled prop 1`] = ` - +> + Touchable + `; diff --git a/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableOpacity-test.js.snap b/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableOpacity-test.js.snap index 4d3f11bc92ef35..92d94f7a1630cb 100644 --- a/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableOpacity-test.js.snap +++ b/Libraries/Components/Touchable/__tests__/__snapshots__/TouchableOpacity-test.js.snap @@ -2,6 +2,15 @@ exports[`TouchableOpacity renders correctly 1`] = ` should be disabled and it should set accessibilityState to d accessibilityRole="button" accessibilityState={ Object { + "busy": undefined, + "checked": undefined, "disabled": true, + "expanded": undefined, + "selected": undefined, } } accessible={true} @@ -59,7 +63,11 @@ exports[`