Feat/accessibility state alias (#34524)
Summary: This adds aliasing for accessibility state, it's used as requested on https://github.com/facebook/react-native/issues/34424. - [aria-disabled](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-disabled) to equivalent [accessibilityState.disabled](https://reactnative.dev/docs/accessibility#accessibilitystate) - [aria-busy](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-busy) to equivalent [accessibilityState.busy](https://reactnative.dev/docs/accessibility#accessibilitystate) - [aria-checked](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-checked) to equivalent [accessibilityState.checked](https://reactnative.dev/docs/accessibility#accessibilitystate) - [aria-expanded](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-expanded) to equivalent [accessibilityState.expanded](https://reactnative.dev/docs/accessibility#accessibilitystate) - [aria-selected](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-selected) to equivalent [accessibilityState.selected](https://reactnative.dev/docs/accessibility#accessibilitystate) ## Changelog [General] [Added] - Add aria-disabled, aria-busy, aria-checked, aria-expanded and aria-selected prop to core components <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://reactnative.dev/contributing/changelogs-in-pull-requests --> Pull Request resolved: https://github.com/facebook/react-native/pull/34524 Test Plan: ```js <View aria-disabled={true} aria-selected={false} aria-checked={true} aria-expanded={true} aria-busy={true} style={{backgroundColor: '#527FE4', padding: 5}}> <Text style={{fontSize: 11}}>Blue background</Text> </View> ``` Reviewed By: cipolleschi Differential Revision: D39137790 Pulled By: jacdebug fbshipit-source-id: 27b5c56e91731ba36bb4754d9862286a7a8191bc
This commit is contained in:
Родитель
a5622165c1
Коммит
98d84e571d
|
@ -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<ButtonProps> {
|
|||
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<ButtonProps> {
|
|||
}
|
||||
}
|
||||
|
||||
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<ButtonProps> {
|
|||
accessibilityHint={accessibilityHint}
|
||||
accessibilityLanguage={accessibilityLanguage}
|
||||
accessibilityRole="button"
|
||||
accessibilityState={accessibilityState}
|
||||
accessibilityState={_accessibilityState}
|
||||
importantForAccessibility={_importantForAccessibility}
|
||||
hasTVPreferredFocus={hasTVPreferredFocus}
|
||||
nextFocusDown={nextFocusDown}
|
||||
|
|
|
@ -52,6 +52,17 @@ 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,
|
||||
/**
|
||||
* A value indicating whether the accessibility elements contained within
|
||||
* this accessibility element are hidden.
|
||||
|
@ -179,9 +190,15 @@ type Props = $ReadOnly<{|
|
|||
* LTI update could not be added via codemod */
|
||||
function Pressable(props: Props, forwardedRef): React.Node {
|
||||
const {
|
||||
accessible,
|
||||
accessibilityState,
|
||||
android_disableSound,
|
||||
android_ripple,
|
||||
accessible,
|
||||
'aria-busy': ariaBusy,
|
||||
'aria-checked': ariaChecked,
|
||||
'aria-disabled': ariaDisabled,
|
||||
'aria-expanded': ariaExpanded,
|
||||
'aria-selected': ariaSelected,
|
||||
cancelable,
|
||||
children,
|
||||
delayHoverIn,
|
||||
|
@ -210,16 +227,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<typeof View> = {
|
||||
...restProps,
|
||||
...android_rippleConfig?.viewProps,
|
||||
accessible: accessible !== false,
|
||||
accessibilityState,
|
||||
accessibilityState: _accessibilityState,
|
||||
focusable: focusable !== false,
|
||||
hitSlop,
|
||||
};
|
||||
|
|
|
@ -2,6 +2,15 @@
|
|||
|
||||
exports[`<Pressable /> should render as expected: should deep render when mocked (please verify output manually) 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
|
@ -21,6 +30,15 @@ exports[`<Pressable /> should render as expected: should deep render when mocked
|
|||
|
||||
exports[`<Pressable /> should render as expected: should deep render when not mocked (please verify output manually) 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={true}
|
||||
|
@ -54,7 +72,11 @@ exports[`<Pressable disabled={true} /> should be disabled when disabled is true:
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -78,7 +100,11 @@ exports[`<Pressable disabled={true} /> should be disabled when disabled is true:
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -118,7 +144,11 @@ exports[`<Pressable disabled={true} accessibilityState={{}} /> should be disable
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -142,7 +172,11 @@ exports[`<Pressable disabled={true} accessibilityState={{}} /> should be disable
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -184,8 +218,11 @@ exports[`<Pressable disabled={true} accessibilityState={{checked: true}} /> shou
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": true,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -209,8 +246,11 @@ exports[`<Pressable disabled={true} accessibilityState={{checked: true}} /> shou
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": true,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -260,7 +300,11 @@ exports[`<Pressable disabled={true} accessibilityState={{disabled: false}} /> sh
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -284,7 +328,11 @@ exports[`<Pressable disabled={true} accessibilityState={{disabled: false}} /> sh
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
|
|
@ -1339,6 +1339,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
|
||||
|
@ -1360,6 +1368,7 @@ function InternalTextInput(props: Props): React.Node {
|
|||
{...props}
|
||||
{...eventHandlers}
|
||||
accessible={accessible}
|
||||
accessibilityState={_accessibilityState}
|
||||
submitBehavior={submitBehavior}
|
||||
caretHidden={caretHidden}
|
||||
dataDetectorTypes={props.dataDetectorTypes}
|
||||
|
@ -1407,6 +1416,7 @@ function InternalTextInput(props: Props): React.Node {
|
|||
{...props}
|
||||
{...eventHandlers}
|
||||
accessible={accessible}
|
||||
accessibilityState={_accessibilityState}
|
||||
autoCapitalize={autoCapitalize}
|
||||
submitBehavior={submitBehavior}
|
||||
caretHidden={caretHidden}
|
||||
|
|
|
@ -2,6 +2,15 @@
|
|||
|
||||
exports[`TextInput tests should render as expected: should deep render when mocked (please verify output manually) 1`] = `
|
||||
<RCTSinglelineTextInputView
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
allowFontScaling={true}
|
||||
focusable={true}
|
||||
|
@ -31,6 +40,15 @@ exports[`TextInput tests should render as expected: should deep render when mock
|
|||
|
||||
exports[`TextInput tests should render as expected: should deep render when not mocked (please verify output manually) 1`] = `
|
||||
<RCTSinglelineTextInputView
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
allowFontScaling={true}
|
||||
focusable={true}
|
||||
|
|
|
@ -131,6 +131,18 @@ class TouchableBounce extends React.Component<Props, State> {
|
|||
const {onBlur, onFocus, ...eventHandlersWithoutBlurAndFocus} =
|
||||
this.state.pressability.getEventHandlers();
|
||||
|
||||
const _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 (
|
||||
<Animated.View
|
||||
style={[{transform: [{scale: this.state.scale}]}, this.props.style]}
|
||||
|
@ -139,7 +151,7 @@ class TouchableBounce extends React.Component<Props, State> {
|
|||
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}
|
||||
|
|
|
@ -162,12 +162,14 @@ class TouchableNativeFeedback extends React.Component<Props, State> {
|
|||
};
|
||||
|
||||
_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<Props, State> {
|
|||
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<Props, State> {
|
|||
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,
|
||||
|
|
|
@ -137,7 +137,10 @@ class TouchableOpacity extends React.Component<Props, State> {
|
|||
_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<Props, State> {
|
|||
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 (
|
||||
<Animated.View
|
||||
|
@ -227,7 +242,7 @@ class TouchableOpacity extends React.Component<Props, State> {
|
|||
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}
|
||||
|
|
|
@ -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,
|
||||
'aria-hidden'?: ?boolean,
|
||||
children?: ?React.Node,
|
||||
delayLongPress?: ?number,
|
||||
|
@ -105,6 +115,18 @@ class TouchableWithoutFeedback extends React.Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
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} =
|
||||
|
@ -116,10 +138,10 @@ class TouchableWithoutFeedback extends React.Component<Props, State> {
|
|||
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,
|
||||
|
||||
|
@ -148,13 +170,16 @@ class TouchableWithoutFeedback extends React.Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
|
@ -1,98 +1,14 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TouchableWithoutFeedback renders correctly 1`] = `
|
||||
<Text
|
||||
accessible={true}
|
||||
focusable={false}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
>
|
||||
Touchable
|
||||
</Text>
|
||||
`;
|
||||
|
||||
exports[`<TouchableNativeFeedback /> should render as expected 1`] = `
|
||||
<View
|
||||
accessible={true}
|
||||
focusable={false}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`<TouchableNativeFeedback disabled={true}> should be disabled when disabled is true 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"disabled": true,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
focusable={false}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`<TouchableNativeFeedback disabled={true} accessibilityState={{}}> should be disabled when disabled is true and accessibilityState is empty 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"disabled": true,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
focusable={false}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`<TouchableNativeFeedback disabled={true} accessibilityState={{checked: true}}> should keep accessibilityState when disabled is true 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"checked": true,
|
||||
"disabled": true,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
focusable={false}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`<TouchableNativeFeedback disabled={true} accessibilityState={{disabled:false}}> should overwrite accessibilityState with value of disabled prop 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"disabled": true,
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -111,7 +27,11 @@ exports[`<TouchableNativeFeedback disabled={false} accessibilityState={{disabled
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -125,3 +45,120 @@ exports[`<TouchableNativeFeedback disabled={false} accessibilityState={{disabled
|
|||
onStartShouldSetResponder={[Function]}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`<TouchableNativeFeedback disabled={true} accessibilityState={{}}> should be disabled when disabled is true and accessibilityState is empty 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
focusable={false}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`<TouchableNativeFeedback disabled={true} accessibilityState={{checked: true}}> should keep accessibilityState when disabled is true 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": true,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
focusable={false}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`<TouchableNativeFeedback disabled={true} accessibilityState={{disabled:false}}> should overwrite accessibilityState with value of disabled prop 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
focusable={false}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`<TouchableNativeFeedback disabled={true}> should be disabled when disabled is true 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
focusable={false}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`TouchableWithoutFeedback renders correctly 1`] = `
|
||||
<Text
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
focusable={false}
|
||||
onClick={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderMove={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={[Function]}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
>
|
||||
Touchable
|
||||
</Text>
|
||||
`;
|
||||
|
|
|
@ -2,6 +2,15 @@
|
|||
|
||||
exports[`TouchableOpacity renders correctly 1`] = `
|
||||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={false}
|
||||
|
@ -28,7 +37,11 @@ exports[`TouchableOpacity renders in disabled state when a disabled prop is pass
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -57,7 +70,11 @@ exports[`TouchableOpacity renders in disabled state when a key disabled in acces
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
|
|
@ -2,6 +2,15 @@
|
|||
|
||||
exports[`TouchableWithoutFeedback renders correctly 1`] = `
|
||||
<Text
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
focusable={false}
|
||||
onClick={[Function]}
|
||||
|
@ -20,7 +29,11 @@ exports[`TouchableWithoutFeedback with disabled state should be disabled when di
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -39,7 +52,11 @@ exports[`TouchableWithoutFeedback with disabled state should be disabled when di
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -58,7 +75,11 @@ exports[`TouchableWithoutFeedback with disabled state should disable button when
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -77,8 +98,11 @@ exports[`TouchableWithoutFeedback with disabled state should keep accessibilityS
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": true,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -97,7 +121,11 @@ exports[`TouchableWithoutFeedback with disabled state should overwrite accessibi
|
|||
<View
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
|
|
@ -43,6 +43,24 @@ const View: React.AbstractComponent<
|
|||
}: ViewProps,
|
||||
forwardedRef,
|
||||
) => {
|
||||
const {
|
||||
accessibilityState,
|
||||
'aria-busy': ariaBusy,
|
||||
'aria-checked': ariaChecked,
|
||||
'aria-disabled': ariaDisabled,
|
||||
'aria-expanded': ariaExpanded,
|
||||
'aria-selected': ariaSelected,
|
||||
...restProps
|
||||
} = otherProps;
|
||||
|
||||
const _accessibilityState = {
|
||||
busy: ariaBusy ?? accessibilityState?.busy,
|
||||
checked: ariaChecked ?? accessibilityState?.checked,
|
||||
disabled: ariaDisabled ?? accessibilityState?.disabled,
|
||||
expanded: ariaExpanded ?? accessibilityState?.expanded,
|
||||
selected: ariaSelected ?? accessibilityState?.selected,
|
||||
};
|
||||
|
||||
// Map role values to AccessibilityRole values
|
||||
const roleToAccessibilityRoleMapping = {
|
||||
alert: 'alert',
|
||||
|
@ -118,6 +136,7 @@ const View: React.AbstractComponent<
|
|||
<TextAncestor.Provider value={false}>
|
||||
<ViewNativeComponent
|
||||
focusable={tabIndex !== undefined ? !tabIndex : focusable}
|
||||
accessibilityState={_accessibilityState}
|
||||
accessibilityRole={
|
||||
role ? roleToAccessibilityRoleMapping[role] : accessibilityRole
|
||||
}
|
||||
|
@ -129,7 +148,7 @@ const View: React.AbstractComponent<
|
|||
? 'no-hide-descendants'
|
||||
: importantForAccessibility
|
||||
}
|
||||
{...otherProps}
|
||||
{...restProps}
|
||||
style={style}
|
||||
pointerEvents={newPointerEvents}
|
||||
ref={forwardedRef}
|
||||
|
|
|
@ -492,7 +492,16 @@ export type ViewProps = $ReadOnly<{|
|
|||
accessibilityLabelledBy?: ?string | ?Array<string>,
|
||||
|
||||
/**
|
||||
* A value indicating whether the accessibility elements contained within
|
||||
* 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,
|
||||
/** A value indicating whether the accessibility elements contained within
|
||||
* this accessibility element are hidden.
|
||||
*
|
||||
* See https://reactnative.dev/docs/view#aria-hidden
|
||||
|
|
|
@ -5,7 +5,11 @@ exports[`<Button /> 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[`<Button /> should be disabled when disabled is empty and accessibilityS
|
|||
accessibilityRole="button"
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -113,7 +121,11 @@ exports[`<Button /> should be disabled when disabled={true} and accessibilitySta
|
|||
accessibilityRole="button"
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -165,6 +177,15 @@ exports[`<Button /> should be disabled when disabled={true} and accessibilitySta
|
|||
exports[`<Button /> should be set importantForAccessibility={no-hide-descendants} when importantForAccessibility={no} 1`] = `
|
||||
<View
|
||||
accessibilityRole="button"
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={false}
|
||||
|
@ -210,6 +231,15 @@ exports[`<Button /> should be set importantForAccessibility={no-hide-descendants
|
|||
exports[`<Button /> should be set importantForAccessibility={no-hide-descendants} when importantForAccessibility={no-hide-descendants} 1`] = `
|
||||
<View
|
||||
accessibilityRole="button"
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={false}
|
||||
|
@ -257,7 +287,11 @@ exports[`<Button /> should not be disabled when disabled={false} and accessibili
|
|||
accessibilityRole="button"
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -307,7 +341,11 @@ exports[`<Button /> should not be disabled when disabled={false} and accessibili
|
|||
accessibilityRole="button"
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": false,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -357,7 +395,11 @@ exports[`<Button /> should overwrite accessibilityState with value of disabled p
|
|||
accessibilityRole="button"
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": true,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
|
@ -409,6 +451,15 @@ exports[`<Button /> should overwrite accessibilityState with value of disabled p
|
|||
exports[`<Button /> should render as expected 1`] = `
|
||||
<View
|
||||
accessibilityRole="button"
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
accessible={true}
|
||||
collapsable={false}
|
||||
focusable={false}
|
||||
|
|
|
@ -178,6 +178,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 (
|
||||
|
|
|
@ -137,14 +137,32 @@ const BaseImage = (props: ImagePropsType, forwardedRef) => {
|
|||
'The <Image> component cannot contain children. If you want to render content on top of the image, consider using the <ImageBackground> component or absolute positioning.',
|
||||
);
|
||||
}
|
||||
const {
|
||||
'aria-busy': ariaBusy,
|
||||
'aria-checked': ariaChecked,
|
||||
'aria-disabled': ariaDisabled,
|
||||
'aria-expanded': ariaExpanded,
|
||||
'aria-selected': ariaSelected,
|
||||
height,
|
||||
src,
|
||||
width,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
const {src, width, height, ...restProps} = props;
|
||||
const _accessibilityState = {
|
||||
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,
|
||||
};
|
||||
|
||||
return (
|
||||
<ImageAnalyticsTagContext.Consumer>
|
||||
{analyticTag => {
|
||||
return (
|
||||
<ImageViewNativeComponent
|
||||
accessibilityState={_accessibilityState}
|
||||
{...restProps}
|
||||
ref={forwardedRef}
|
||||
style={style}
|
||||
|
|
|
@ -12,6 +12,15 @@ exports[`<Image /> should render as <Image> when mocked 1`] = `
|
|||
|
||||
exports[`<Image /> should render as <RCTImageView> when not mocked 1`] = `
|
||||
<RCTImageView
|
||||
accessibilityState={
|
||||
Object {
|
||||
"busy": undefined,
|
||||
"checked": undefined,
|
||||
"disabled": undefined,
|
||||
"expanded": undefined,
|
||||
"selected": undefined,
|
||||
}
|
||||
}
|
||||
internal_analyticTag={null}
|
||||
resizeMode="cover"
|
||||
source={
|
||||
|
|
|
@ -34,6 +34,11 @@ const Text: React.AbstractComponent<
|
|||
const {
|
||||
accessible,
|
||||
allowFontScaling,
|
||||
'aria-busy': ariaBusy,
|
||||
'aria-checked': ariaChecked,
|
||||
'aria-disabled': ariaDisabled,
|
||||
'aria-expanded': ariaExpanded,
|
||||
'aria-selected': ariaSelected,
|
||||
ellipsizeMode,
|
||||
onLongPress,
|
||||
onPress,
|
||||
|
@ -52,14 +57,23 @@ const Text: React.AbstractComponent<
|
|||
|
||||
const [isHighlighted, setHighlighted] = useState(false);
|
||||
|
||||
const _accessibilityState = {
|
||||
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,
|
||||
};
|
||||
|
||||
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 ||
|
||||
|
@ -186,6 +200,7 @@ const Text: React.AbstractComponent<
|
|||
return hasTextAncestor ? (
|
||||
<NativeVirtualText
|
||||
{...restProps}
|
||||
accessibilityState={_accessibilityState}
|
||||
{...eventHandlersForText}
|
||||
isHighlighted={isHighlighted}
|
||||
isPressable={isPressable}
|
||||
|
@ -203,7 +218,7 @@ const Text: React.AbstractComponent<
|
|||
disabled={_disabled}
|
||||
selectable={_selectable}
|
||||
accessible={_accessible}
|
||||
accessibilityState={_accessibilityState}
|
||||
accessibilityState={nativeTextAccessibilityState}
|
||||
allowFontScaling={allowFontScaling !== false}
|
||||
ellipsizeMode={ellipsizeMode ?? 'tail'}
|
||||
isHighlighted={isHighlighted}
|
||||
|
|
|
@ -77,6 +77,17 @@ export type TextProps = $ReadOnly<{|
|
|||
*
|
||||
*/
|
||||
android_hyphenationFrequency?: ?('normal' | 'none' | 'full'),
|
||||
|
||||
/**
|
||||
* 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?: ?Node,
|
||||
|
||||
/**
|
||||
|
|
|
@ -220,6 +220,17 @@ class AccessibilityExample extends React.Component<{}> {
|
|||
</View>
|
||||
</RNTesterBlock>
|
||||
|
||||
<RNTesterBlock title="View with label, hint, role, and state">
|
||||
<View
|
||||
accessible={true}
|
||||
accessibilityLabel="Accessibility label."
|
||||
accessibilityRole="button"
|
||||
aria-selected={true}
|
||||
accessibilityHint="Accessibility hint.">
|
||||
<Text>Accessible view with label, hint, role, and state</Text>
|
||||
</View>
|
||||
</RNTesterBlock>
|
||||
|
||||
<RNTesterBlock title="TextInput with accessibilityLabelledBy attribute">
|
||||
<View>
|
||||
<Text nativeID="formLabel1">Mail Address</Text>
|
||||
|
|
Загрузка…
Ссылка в новой задаче