Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(fabric, a11y): implement accessibility role #2293

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably ifdef this for iOS vs macOS


/**
* Insets used when hit testing inside this view.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#import <React/RCTConversions.h>
#import <React/RCTCursor.h> // [macOS]
#import <React/RCTLocalizedString.h>
#import <React/UIView+React.h> // [macOS]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this import?

#import <react/featureflags/ReactNativeFeatureFlags.h>
#import <react/renderer/components/view/ViewComponentDescriptor.h>
#import <react/renderer/components/view/ViewEventEmitter.h>
Expand Down Expand Up @@ -373,10 +374,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`
Expand All @@ -392,9 +396,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;
Expand All @@ -404,6 +413,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) {
Expand All @@ -427,10 +437,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);
Expand All @@ -447,6 +462,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) {
Expand All @@ -465,8 +481,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:);
Expand Down Expand Up @@ -1236,7 +1251,7 @@ - (void)clearExistingGradientLayers

#pragma mark - Accessibility

- (NSObject *)accessibilityElement
- (RCTPlatformView *)accessibilityElement
{
return self;
}
Expand Down
94 changes: 93 additions & 1 deletion packages/react-native/React/Fabric/RCTConversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,99 @@ inline UIAccessibilityTraits RCTUIAccessibilityTraitsFromAccessibilityTraits(
}
return result;
};
#endif // [macOS]
#else // [macOS
inline NSAccessibilityRole RCTUIAccessibilityRoleFromAccessibilityTraits(
facebook::react::AccessibilityTraits accessibilityTraits)
{
Comment on lines +128 to +130
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double check this list with paper

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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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|(
Expand Down
Loading