From fd8a3456cac72634cc149904e157e07257dbf364 Mon Sep 17 00:00:00 2001 From: Jorge Cabiedes Acosta Date: Mon, 28 Apr 2025 11:15:35 -0700 Subject: [PATCH] Add `accessibilityRespondsToUserInteraction` prop (#50837) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/50837 This prop can be used to disable user interaction with switch control, voice control or full keyboard access. VoiceOver is not affected by it. https://developer.apple.com/documentation/swiftui/view/accessibilityrespondstouserinteraction(_:) Changelog: [iOS][Added] - Expose iOS's accessibilityRespondsToUserInteraction as a prop Reviewed By: joevilches Differential Revision: D73382060 fbshipit-source-id: c9f3137adc0ea34a58435f7f0438748fbfcc5a18 --- .../Libraries/Components/View/ViewAccessibility.d.ts | 8 ++++++++ .../Libraries/Components/View/ViewAccessibility.js | 8 ++++++++ .../Libraries/NativeComponent/BaseViewConfig.ios.js | 1 + .../__tests__/__snapshots__/public-api-test.js.snap | 1 + .../ComponentViews/View/RCTViewComponentView.mm | 5 +++++ .../renderer/components/view/AccessibilityProps.cpp | 10 ++++++++++ .../renderer/components/view/AccessibilityProps.h | 1 + 7 files changed, 34 insertions(+) diff --git a/packages/react-native/Libraries/Components/View/ViewAccessibility.d.ts b/packages/react-native/Libraries/Components/View/ViewAccessibility.d.ts index bf4bee39538..1d6d060b9ca 100644 --- a/packages/react-native/Libraries/Components/View/ViewAccessibility.d.ts +++ b/packages/react-native/Libraries/Components/View/ViewAccessibility.d.ts @@ -334,6 +334,14 @@ export interface AccessibilityPropsIOS { * @platform ios */ accessibilityLargeContentTitle?: string | undefined; + + /** + * Blocks the user from interacting with the component through keyboard while still allowing + * screen reader to interact with it if this View is still accessible. + * + * @platform ios + */ + accessibilityRespondsToUserInteraction?: boolean | undefined; } export type Role = diff --git a/packages/react-native/Libraries/Components/View/ViewAccessibility.js b/packages/react-native/Libraries/Components/View/ViewAccessibility.js index 08ba5e0a047..2f58e94c19f 100644 --- a/packages/react-native/Libraries/Components/View/ViewAccessibility.js +++ b/packages/react-native/Libraries/Components/View/ViewAccessibility.js @@ -320,6 +320,14 @@ export type AccessibilityPropsIOS = $ReadOnly<{ * @platform ios */ accessibilityLanguage?: ?Stringish, + + /** + * Blocks the user from interacting with the component through keyboard while still allowing + * screen reader to interact with it if this View is still accessible. + * + * @platform ios + */ + accessibilityRespondsToUserInteraction?: ?boolean, }>; export type AccessibilityProps = $ReadOnly<{ diff --git a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js index db650a8d123..b753491382e 100644 --- a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js +++ b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js @@ -198,6 +198,7 @@ const validAttributesForNonEventProps = { accessibilityShowsLargeContentViewer: true, accessibilityLargeContentTitle: true, experimental_accessibilityOrder: true, + accessibilityRespondsToUserInteraction: true, testID: true, backgroundColor: {process: require('../StyleSheet/processColor').default}, backfaceVisibility: true, diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index cc22f27f7d7..163b751f46f 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -3652,6 +3652,7 @@ export type AccessibilityPropsIOS = $ReadOnly<{ \\"aria-modal\\"?: ?boolean, accessibilityElementsHidden?: ?boolean, accessibilityLanguage?: ?Stringish, + accessibilityRespondsToUserInteraction?: ?boolean, }>; export type AccessibilityProps = $ReadOnly<{ ...AccessibilityPropsAndroid, diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 92b8b1d6309..ce5aab7b273 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -440,6 +440,11 @@ const CGFloat BACKGROUND_COLOR_ZPOSITION = -1024.0f; } } + if (oldViewProps.accessibilityRespondsToUserInteraction != newViewProps.accessibilityRespondsToUserInteraction) { + self.accessibilityElement.accessibilityRespondsToUserInteraction = + newViewProps.accessibilityRespondsToUserInteraction; + } + // `testId` if (oldViewProps.testId != newViewProps.testId) { SEL setAccessibilityIdentifierSelector = @selector(setAccessibilityIdentifier:); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp index 4106ab06d55..9b96f996548 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp @@ -154,6 +154,15 @@ AccessibilityProps::AccessibilityProps( "accessibilityIgnoresInvertColors", sourceProps.accessibilityIgnoresInvertColors, false)), + accessibilityRespondsToUserInteraction( + ReactNativeFeatureFlags::enableCppPropsIteratorSetter() + ? sourceProps.accessibilityRespondsToUserInteraction + : convertRawProp( + context, + rawProps, + "accessibilityRespondsToUserInteraction", + sourceProps.accessibilityRespondsToUserInteraction, + {})), onAccessibilityTap( ReactNativeFeatureFlags::enableCppPropsIteratorSetter() ? sourceProps.onAccessibilityTap @@ -266,6 +275,7 @@ void AccessibilityProps::setProp( RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityViewIsModal); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityElementsHidden); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityIgnoresInvertColors); + RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityRespondsToUserInteraction); RAW_SET_PROP_SWITCH_CASE_BASIC(onAccessibilityTap); RAW_SET_PROP_SWITCH_CASE_BASIC(onAccessibilityMagicTap); RAW_SET_PROP_SWITCH_CASE_BASIC(onAccessibilityEscape); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.h index c0f8c3bbcfd..f6686eb76c8 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.h @@ -49,6 +49,7 @@ class AccessibilityProps { bool accessibilityViewIsModal{false}; bool accessibilityElementsHidden{false}; bool accessibilityIgnoresInvertColors{false}; + bool accessibilityRespondsToUserInteraction{}; bool onAccessibilityTap{}; bool onAccessibilityMagicTap{}; bool onAccessibilityEscape{};