diff --git a/packages/react-native/Libraries/Components/View/ReactNativeViewAttributes.js b/packages/react-native/Libraries/Components/View/ReactNativeViewAttributes.js index 88dab482c47..d07a319837a 100644 --- a/packages/react-native/Libraries/Components/View/ReactNativeViewAttributes.js +++ b/packages/react-native/Libraries/Components/View/ReactNativeViewAttributes.js @@ -22,6 +22,8 @@ const UIView = { accessibilityValue: true, accessibilityHint: true, accessibilityLanguage: true, + accessibilityShowsLargeContentViewer: true, + accessibilityLargeContentTitle: true, importantForAccessibility: true, nativeID: true, testID: true, diff --git a/packages/react-native/Libraries/Components/View/ViewAccessibility.d.ts b/packages/react-native/Libraries/Components/View/ViewAccessibility.d.ts index 90cca7b66a1..bf4bee39538 100644 --- a/packages/react-native/Libraries/Components/View/ViewAccessibility.d.ts +++ b/packages/react-native/Libraries/Components/View/ViewAccessibility.d.ts @@ -319,6 +319,21 @@ export interface AccessibilityPropsIOS { * @platform ios */ accessibilityLanguage?: string | undefined; + + /** + * A Boolean value that indicates whether or not to show the item in the large content viewer. + * Available on iOS 13.0+ + * https://reactnative.dev/docs/accessibility#accessibilityshowslargecontentviewer + * @platform ios + */ + accessibilityShowsLargeContentViewer?: boolean | undefined; + + /** + * When `accessibilityShowsLargeContentViewer` is set, this string will be used as title for the large content viewer. + * https://reactnative.dev/docs/accessibility#accessibilitylargecontenttitle + * @platform ios + */ + accessibilityLargeContentTitle?: string | undefined; } export type Role = diff --git a/packages/react-native/Libraries/Components/View/ViewPropTypes.js b/packages/react-native/Libraries/Components/View/ViewPropTypes.js index 53dfa6a5cc3..00d90a87e30 100644 --- a/packages/react-native/Libraries/Components/View/ViewPropTypes.js +++ b/packages/react-native/Libraries/Components/View/ViewPropTypes.js @@ -415,6 +415,20 @@ type IOSViewProps = $ReadOnly<{| */ accessibilityViewIsModal?: ?boolean, + /** + * @platform ios + * + * See https://reactnative.dev/docs/view#accessibilityshowslargecontentviewer + */ + accessibilityShowsLargeContentViewer?: ?boolean, + + /** + * @platform ios + * + * See https://reactnative.dev/docs/view#accessibilitylargecontenttitle + */ + accessibilityLargeContentTitle?: ?string, + /** * The aria-modal attribute indicates content contained within a modal with aria-modal="true" * should be accessible to the user. diff --git a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js index 378b5c272dc..bcea251752d 100644 --- a/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js +++ b/packages/react-native/Libraries/NativeComponent/BaseViewConfig.ios.js @@ -193,6 +193,8 @@ const validAttributesForNonEventProps = { accessibilityViewIsModal: true, accessibilityElementsHidden: true, accessibilityIgnoresInvertColors: true, + accessibilityShowsLargeContentViewer: true, + accessibilityLargeContentTitle: 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 beab205c536..ad9ca9e408a 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 @@ -3891,6 +3891,8 @@ exports[`public API should not change unintentionally Libraries/Components/View/ accessibilityValue: true, accessibilityHint: true, accessibilityLanguage: true, + accessibilityShowsLargeContentViewer: true, + accessibilityLargeContentTitle: true, importantForAccessibility: true, nativeID: true, testID: true, @@ -4177,6 +4179,8 @@ type AndroidViewProps = $ReadOnly<{| type IOSViewProps = $ReadOnly<{| accessibilityIgnoresInvertColors?: ?boolean, accessibilityViewIsModal?: ?boolean, + accessibilityShowsLargeContentViewer?: ?boolean, + accessibilityLargeContentTitle?: ?string, \\"aria-modal\\"?: ?boolean, accessibilityElementsHidden?: ?boolean, accessibilityLanguage?: ?Stringish, 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 ef5ef9b2d4a..883e91b5d13 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -347,6 +347,26 @@ using namespace facebook::react; self.accessibilityElement.accessibilityElementsHidden = newViewProps.accessibilityElementsHidden; } + // `accessibilityShowsLargeContentViewer` + if (oldViewProps.accessibilityShowsLargeContentViewer != newViewProps.accessibilityShowsLargeContentViewer) { + if (@available(iOS 13.0, *)) { + if (newViewProps.accessibilityShowsLargeContentViewer) { + self.showsLargeContentViewer = YES; + UILargeContentViewerInteraction *interaction = [[UILargeContentViewerInteraction alloc] init]; + [self addInteraction:interaction]; + } else { + self.showsLargeContentViewer = NO; + } + } + } + + // `accessibilityLargeContentTitle` + if (oldViewProps.accessibilityLargeContentTitle != newViewProps.accessibilityLargeContentTitle) { + if (@available(iOS 13.0, *)) { + self.largeContentTitle = RCTNSStringFromStringNilIfEmpty(newViewProps.accessibilityLargeContentTitle); + } + } + // `accessibilityTraits` if (oldViewProps.accessibilityTraits != newViewProps.accessibilityTraits) { self.accessibilityElement.accessibilityTraits = diff --git a/packages/react-native/React/Views/RCTViewManager.m b/packages/react-native/React/Views/RCTViewManager.m index a657565d7b8..223b89ecaeb 100644 --- a/packages/react-native/React/Views/RCTViewManager.m +++ b/packages/react-native/React/Views/RCTViewManager.m @@ -295,6 +295,28 @@ RCT_CUSTOM_VIEW_PROPERTY(accessibilityState, NSDictionary, RCTView) } } +RCT_CUSTOM_VIEW_PROPERTY(accessibilityShowsLargeContentViewer, BOOL, RCTView) +{ + if (@available(iOS 13.0, *)) { + BOOL showsLargeContentViewer = json ? [RCTConvert BOOL:json] : defaultView.showsLargeContentViewer; + + if (showsLargeContentViewer) { + view.showsLargeContentViewer = YES; + UILargeContentViewerInteraction *interaction = [[UILargeContentViewerInteraction alloc] init]; + [view addInteraction:interaction]; + } else { + view.showsLargeContentViewer = NO; + } + } +} + +RCT_CUSTOM_VIEW_PROPERTY(accessibilityLargeContentTitle, NSString, RCTView) +{ + if (@available(iOS 13.0, *)) { + view.largeContentTitle = json ? [RCTConvert NSString:json] : defaultView.largeContentTitle; + } +} + RCT_CUSTOM_VIEW_PROPERTY(nativeID, NSString *, RCTView) { view.nativeID = json ? [RCTConvert NSString:json] : defaultView.nativeID; 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 bb5e7a6f288..56b4c335ad8 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp @@ -81,6 +81,15 @@ AccessibilityProps::AccessibilityProps( "accessibilityLanguage", sourceProps.accessibilityLanguage, "")), + accessibilityLargeContentTitle( + CoreFeatures::enablePropIteratorSetter + ? sourceProps.accessibilityLargeContentTitle + : convertRawProp( + context, + rawProps, + "accessibilityLargeContentTitle", + sourceProps.accessibilityLargeContentTitle, + "")), accessibilityValue( CoreFeatures::enablePropIteratorSetter ? sourceProps.accessibilityValue @@ -99,6 +108,15 @@ AccessibilityProps::AccessibilityProps( "accessibilityActions", sourceProps.accessibilityActions, {})), + accessibilityShowsLargeContentViewer( + CoreFeatures::enablePropIteratorSetter + ? sourceProps.accessibilityShowsLargeContentViewer + : convertRawProp( + context, + rawProps, + "accessibilityShowsLargeContentViewer", + sourceProps.accessibilityShowsLargeContentViewer, + false)), accessibilityViewIsModal( CoreFeatures::enablePropIteratorSetter ? sourceProps.accessibilityViewIsModal @@ -229,6 +247,8 @@ void AccessibilityProps::setProp( RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLabelledBy); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityHint); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLanguage); + RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityShowsLargeContentViewer); + RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLargeContentTitle); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityValue); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityActions); RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityViewIsModal); 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 a46c21412d5..77db5750114 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.h @@ -41,8 +41,10 @@ class AccessibilityProps { std::string accessibilityRole{""}; std::string accessibilityHint{""}; std::string accessibilityLanguage{""}; + std::string accessibilityLargeContentTitle{""}; AccessibilityValue accessibilityValue; std::vector accessibilityActions{}; + bool accessibilityShowsLargeContentViewer{false}; bool accessibilityViewIsModal{false}; bool accessibilityElementsHidden{false}; bool accessibilityIgnoresInvertColors{false};