diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h index 7a903401112fa8..3d7564de46e8b1 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h @@ -56,7 +56,7 @@ NS_ASSUME_NONNULL_BEGIN * transparent in favour of some subview. * Defaults to `self`. */ -@property (nonatomic, strong, nullable, readonly) NSObject *accessibilityElement; +@property (nonatomic, strong, nullable, readonly) RCTPlatformView *accessibilityElement; // [macOS] /** * Insets used when hit testing inside this view. 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 55fac1ea49bf0e..2c789467999558 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -19,6 +19,7 @@ #import // [macOS] #import #import +#import // [macOS] #import #import #import @@ -384,10 +385,13 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & self.nativeId = RCTNSStringFromStringNilIfEmpty(newViewProps.nativeId); } -#if !TARGET_OS_OSX // [macOS] // `accessible` if (oldViewProps.accessible != newViewProps.accessible) { +#if !TARGET_OS_OSX // [macOS] self.accessibilityElement.isAccessibilityElement = newViewProps.accessible; +#else // [macOS + self.accessibilityElement.accessibilityElement = newViewProps.accessible; +#endif // macOS] } // `accessibilityLabel` @@ -403,9 +407,14 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & // `accessibilityHint` if (oldViewProps.accessibilityHint != newViewProps.accessibilityHint) { +#if !TARGET_OS_OSX // [macOS] self.accessibilityElement.accessibilityHint = RCTNSStringFromStringNilIfEmpty(newViewProps.accessibilityHint); +#else // [macOS + self.accessibilityElement.accessibilityHelp = RCTNSStringFromStringNilIfEmpty(newViewProps.accessibilityHint); +#endif // macOS] } +#if !TARGET_OS_OSX // [macOS] // `accessibilityViewIsModal` if (oldViewProps.accessibilityViewIsModal != newViewProps.accessibilityViewIsModal) { self.accessibilityElement.accessibilityViewIsModal = newViewProps.accessibilityViewIsModal; @@ -415,6 +424,7 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & if (oldViewProps.accessibilityElementsHidden != newViewProps.accessibilityElementsHidden) { self.accessibilityElement.accessibilityElementsHidden = newViewProps.accessibilityElementsHidden; } +#endif // [macOS] // `accessibilityShowsLargeContentViewer` if (oldViewProps.accessibilityShowsLargeContentViewer != newViewProps.accessibilityShowsLargeContentViewer) { @@ -438,10 +448,15 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & // `accessibilityTraits` if (oldViewProps.accessibilityTraits != newViewProps.accessibilityTraits) { +#if !TARGET_OS_OSX // [macOS] self.accessibilityElement.accessibilityTraits = RCTUIAccessibilityTraitsFromAccessibilityTraits(newViewProps.accessibilityTraits); +#else // [macOS + self.accessibilityElement.accessibilityRole = RCTUIAccessibilityRoleFromAccessibilityTraits(newViewProps.accessibilityTraits); +#endif // macOS] } +#if !TARGET_OS_OSX // [macOS] // `accessibilityState` if (oldViewProps.accessibilityState != newViewProps.accessibilityState) { self.accessibilityTraits &= ~(UIAccessibilityTraitNotEnabled | UIAccessibilityTraitSelected); @@ -458,6 +473,7 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & if (oldViewProps.accessibilityIgnoresInvertColors != newViewProps.accessibilityIgnoresInvertColors) { self.accessibilityIgnoresInvertColors = newViewProps.accessibilityIgnoresInvertColors; } +#endif // [macOS] // `accessibilityValue` if (oldViewProps.accessibilityValue != newViewProps.accessibilityValue) { @@ -476,8 +492,7 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & self.accessibilityElement.accessibilityValue = nil; } } -#endif // [macOS] - + // `testId` if (oldViewProps.testId != newViewProps.testId) { SEL setAccessibilityIdentifierSelector = @selector(setAccessibilityIdentifier:); @@ -1303,7 +1318,7 @@ - (void)clearExistingBackgroundImageLayers #pragma mark - Accessibility -- (NSObject *)accessibilityElement +- (RCTPlatformView *)accessibilityElement { return self; } diff --git a/packages/react-native/React/Fabric/RCTConversions.h b/packages/react-native/React/Fabric/RCTConversions.h index 66ce1342716a7a..f6047c092e3d69 100644 --- a/packages/react-native/React/Fabric/RCTConversions.h +++ b/packages/react-native/React/Fabric/RCTConversions.h @@ -130,7 +130,99 @@ inline UIAccessibilityTraits RCTUIAccessibilityTraitsFromAccessibilityTraits( } return result; }; -#endif // [macOS] +#else // [macOS +inline NSAccessibilityRole RCTUIAccessibilityRoleFromAccessibilityTraits( + facebook::react::AccessibilityTraits accessibilityTraits) +{ + using AccessibilityTraits = facebook::react::AccessibilityTraits; + if ((accessibilityTraits & AccessibilityTraits::Button) != AccessibilityTraits::None) { + if ((accessibilityTraits & AccessibilityTraits::Bar) != AccessibilityTraits::None) { + return NSAccessibilityToolbarRole; + } + if ((accessibilityTraits & AccessibilityTraits::PopUp) != AccessibilityTraits::None) { + return NSAccessibilityPopUpButtonRole; + } + if ((accessibilityTraits & AccessibilityTraits::Menu) != AccessibilityTraits::None) { + return NSAccessibilityMenuButtonRole; + } + return NSAccessibilityButtonRole; + } + if ((accessibilityTraits & AccessibilityTraits::Link) != AccessibilityTraits::None) { + return NSAccessibilityLinkRole; + } + if ((accessibilityTraits & AccessibilityTraits::Image) != AccessibilityTraits::None) { + return NSAccessibilityImageRole; + } + if ((accessibilityTraits & AccessibilityTraits::KeyboardKey) != AccessibilityTraits::None) { + return NSAccessibilityButtonRole; + } + if ((accessibilityTraits & AccessibilityTraits::StaticText) != AccessibilityTraits::None) { + return NSAccessibilityStaticTextRole; + } + if ((accessibilityTraits & AccessibilityTraits::SummaryElement) != AccessibilityTraits::None) { + return NSAccessibilityStaticTextRole; + } + if ((accessibilityTraits & AccessibilityTraits::SearchField) != AccessibilityTraits::None) { + return NSAccessibilityTextFieldRole; + } + if ((accessibilityTraits & AccessibilityTraits::Adjustable) != AccessibilityTraits::None) { + return NSAccessibilitySliderRole; + } + if ((accessibilityTraits & AccessibilityTraits::Header) != AccessibilityTraits::None) { + return NSAccessibilityStaticTextRole; + } + if ((accessibilityTraits & AccessibilityTraits::Switch) != AccessibilityTraits::None) { + return NSAccessibilityCheckBoxRole; + } + if ((accessibilityTraits & AccessibilityTraits::UpdatesFrequently) != AccessibilityTraits::None) { + return NSAccessibilityProgressIndicatorRole; + } + if ((accessibilityTraits & AccessibilityTraits::ComboBox) != AccessibilityTraits::None) { + return NSAccessibilityComboBoxRole; + } + if ((accessibilityTraits & AccessibilityTraits::Menu) != AccessibilityTraits::None) { + if ((accessibilityTraits & AccessibilityTraits::Bar) != AccessibilityTraits::None) { + return NSAccessibilityMenuBarRole; + } + if ((accessibilityTraits & AccessibilityTraits::Item) != AccessibilityTraits::None) { + return NSAccessibilityMenuItemRole; + } + return NSAccessibilityMenuRole; + } + if ((accessibilityTraits & AccessibilityTraits::Radio) != AccessibilityTraits::None) { + if ((accessibilityTraits & AccessibilityTraits::Group) != AccessibilityTraits::None) { + return NSAccessibilityRadioGroupRole; + } + return NSAccessibilityRadioButtonRole; + } + if ((accessibilityTraits & AccessibilityTraits::ScrollBar) != AccessibilityTraits::None) { + return NSAccessibilityScrollBarRole; + } + if ((accessibilityTraits & AccessibilityTraits::SpinButton) != AccessibilityTraits::None) { + return NSAccessibilityIncrementorRole; + } + if ((accessibilityTraits & AccessibilityTraits::Tab) != AccessibilityTraits::None) { + if ((accessibilityTraits & AccessibilityTraits::List) != AccessibilityTraits::None) { + return NSAccessibilityTabGroupRole; + } + return NSAccessibilityButtonRole; + } + if ((accessibilityTraits & AccessibilityTraits::Disclosure) != AccessibilityTraits::None) { + return NSAccessibilityDisclosureTriangleRole; + } + if ((accessibilityTraits & AccessibilityTraits::Group) != AccessibilityTraits::None) { + return NSAccessibilityGroupRole; + } + if ((accessibilityTraits & AccessibilityTraits::List) != AccessibilityTraits::None) { + return NSAccessibilityListRole; + } + if ((accessibilityTraits & AccessibilityTraits::Table) != AccessibilityTraits::None) { + return NSAccessibilityTableRole; + } + + return NSAccessibilityUnknownRole; +}; +#endif // macOS] inline CATransform3D RCTCATransform3DFromTransformMatrix(const facebook::react::Transform &transformMatrix) { diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h index 420a10852af33d..06e9fc9b94e11a 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h @@ -34,6 +34,21 @@ enum class AccessibilityTraits : uint32_t { Header = (1 << 15), Switch = (1 << 16), TabBar = (1 << 17), +// [macOS + ComboBox = (1 << 18), + Menu = (1 << 19), + PopUp = (1 << 20), + Bar = (1 << 21), + Item = (1 << 22), + Group = (1 << 23), + List = (1 << 24), + Tab = (1 << 25), + Table = (1 << 26), + Disclosure = (1 << 27), + Radio = (1 << 28), + ScrollBar = (1 << 29), + SpinButton = (1 << 30), +// macOS] }; constexpr enum AccessibilityTraits operator|(