Skip to content

Commit b4b142a

Browse files
authored
fix(fabric, a11y): implement accessibility role (#2293)
1 parent 85494db commit b4b142a

File tree

4 files changed

+138
-4
lines changed

4 files changed

+138
-4
lines changed

packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ NS_ASSUME_NONNULL_BEGIN
5656
* transparent in favour of some subview.
5757
* Defaults to `self`.
5858
*/
59+
#if !TARGET_OS_OSX // [macOS]
5960
@property (nonatomic, strong, nullable, readonly) NSObject *accessibilityElement;
61+
#else // [macOS
62+
@property (nonatomic, strong, nullable, readonly) NSView *accessibilityElement;
63+
#endif // macOS]
6064

6165
/**
6266
* Insets used when hit testing inside this view.

packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,28 +384,38 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
384384
self.nativeId = RCTNSStringFromStringNilIfEmpty(newViewProps.nativeId);
385385
}
386386

387-
#if !TARGET_OS_OSX // [macOS]
388387
// `accessible`
389388
if (oldViewProps.accessible != newViewProps.accessible) {
389+
#if !TARGET_OS_OSX // [macOS]
390390
self.accessibilityElement.isAccessibilityElement = newViewProps.accessible;
391+
#else // [macOS
392+
self.accessibilityElement.accessibilityElement = newViewProps.accessible;
393+
#endif // macOS]
391394
}
392395

393396
// `accessibilityLabel`
394397
if (oldViewProps.accessibilityLabel != newViewProps.accessibilityLabel) {
395398
self.accessibilityElement.accessibilityLabel = RCTNSStringFromStringNilIfEmpty(newViewProps.accessibilityLabel);
396399
}
397400

401+
#if !TARGET_OS_OSX // [macOS]
398402
// `accessibilityLanguage`
399403
if (oldViewProps.accessibilityLanguage != newViewProps.accessibilityLanguage) {
400404
self.accessibilityElement.accessibilityLanguage =
401405
RCTNSStringFromStringNilIfEmpty(newViewProps.accessibilityLanguage);
402406
}
407+
#endif // [macOS]
403408

404409
// `accessibilityHint`
405410
if (oldViewProps.accessibilityHint != newViewProps.accessibilityHint) {
411+
#if !TARGET_OS_OSX // [macOS]
406412
self.accessibilityElement.accessibilityHint = RCTNSStringFromStringNilIfEmpty(newViewProps.accessibilityHint);
413+
#else // [macOS
414+
self.accessibilityElement.accessibilityHelp = RCTNSStringFromStringNilIfEmpty(newViewProps.accessibilityHint);
415+
#endif // macOS]
407416
}
408417

418+
#if !TARGET_OS_OSX // [macOS]
409419
// `accessibilityViewIsModal`
410420
if (oldViewProps.accessibilityViewIsModal != newViewProps.accessibilityViewIsModal) {
411421
self.accessibilityElement.accessibilityViewIsModal = newViewProps.accessibilityViewIsModal;
@@ -435,13 +445,19 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
435445
self.largeContentTitle = RCTNSStringFromStringNilIfEmpty(newViewProps.accessibilityLargeContentTitle);
436446
}
437447
}
448+
#endif // [macOS]
438449

439450
// `accessibilityTraits`
440451
if (oldViewProps.accessibilityTraits != newViewProps.accessibilityTraits) {
452+
#if !TARGET_OS_OSX // [macOS]
441453
self.accessibilityElement.accessibilityTraits =
442454
RCTUIAccessibilityTraitsFromAccessibilityTraits(newViewProps.accessibilityTraits);
455+
#else // [macOS
456+
self.accessibilityElement.accessibilityRole = RCTUIAccessibilityRoleFromAccessibilityTraits(newViewProps.accessibilityTraits);
457+
#endif // macOS]
443458
}
444459

460+
#if !TARGET_OS_OSX // [macOS]
445461
// `accessibilityState`
446462
if (oldViewProps.accessibilityState != newViewProps.accessibilityState) {
447463
self.accessibilityTraits &= ~(UIAccessibilityTraitNotEnabled | UIAccessibilityTraitSelected);
@@ -458,6 +474,7 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
458474
if (oldViewProps.accessibilityIgnoresInvertColors != newViewProps.accessibilityIgnoresInvertColors) {
459475
self.accessibilityIgnoresInvertColors = newViewProps.accessibilityIgnoresInvertColors;
460476
}
477+
#endif // [macOS]
461478

462479
// `accessibilityValue`
463480
if (oldViewProps.accessibilityValue != newViewProps.accessibilityValue) {
@@ -476,8 +493,7 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
476493
self.accessibilityElement.accessibilityValue = nil;
477494
}
478495
}
479-
#endif // [macOS]
480-
496+
481497
// `testId`
482498
if (oldViewProps.testId != newViewProps.testId) {
483499
SEL setAccessibilityIdentifierSelector = @selector(setAccessibilityIdentifier:);
@@ -1303,7 +1319,11 @@ - (void)clearExistingBackgroundImageLayers
13031319

13041320
#pragma mark - Accessibility
13051321

1322+
#if !TARGET_OS_OSX // [macOS]
13061323
- (NSObject *)accessibilityElement
1324+
#else // [macOS
1325+
- (NSView *)accessibilityElement // macOS]
1326+
#endif // macOS]
13071327
{
13081328
return self;
13091329
}

packages/react-native/React/Fabric/RCTConversions.h

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,102 @@ inline UIAccessibilityTraits RCTUIAccessibilityTraitsFromAccessibilityTraits(
130130
}
131131
return result;
132132
};
133-
#endif // [macOS]
133+
#else // [macOS
134+
inline NSAccessibilityRole RCTUIAccessibilityRoleFromAccessibilityTraits(
135+
facebook::react::AccessibilityTraits accessibilityTraits)
136+
{
137+
using AccessibilityTraits = facebook::react::AccessibilityTraits;
138+
if ((accessibilityTraits & AccessibilityTraits::Button) != AccessibilityTraits::None) {
139+
if ((accessibilityTraits & AccessibilityTraits::Bar) != AccessibilityTraits::None) {
140+
return NSAccessibilityToolbarRole;
141+
}
142+
if ((accessibilityTraits & AccessibilityTraits::PopUp) != AccessibilityTraits::None) {
143+
return NSAccessibilityPopUpButtonRole;
144+
}
145+
if ((accessibilityTraits & AccessibilityTraits::Menu) != AccessibilityTraits::None) {
146+
return NSAccessibilityMenuButtonRole;
147+
}
148+
return NSAccessibilityButtonRole;
149+
}
150+
if ((accessibilityTraits & AccessibilityTraits::Link) != AccessibilityTraits::None) {
151+
return NSAccessibilityLinkRole;
152+
}
153+
if ((accessibilityTraits & AccessibilityTraits::Image) != AccessibilityTraits::None) {
154+
return NSAccessibilityImageRole;
155+
}
156+
if ((accessibilityTraits & AccessibilityTraits::KeyboardKey) != AccessibilityTraits::None) {
157+
return NSAccessibilityButtonRole;
158+
}
159+
if ((accessibilityTraits & AccessibilityTraits::StaticText) != AccessibilityTraits::None) {
160+
return NSAccessibilityStaticTextRole;
161+
}
162+
if ((accessibilityTraits & AccessibilityTraits::SummaryElement) != AccessibilityTraits::None) {
163+
return NSAccessibilityStaticTextRole;
164+
}
165+
if ((accessibilityTraits & AccessibilityTraits::UpdatesFrequently) != AccessibilityTraits::None) {
166+
return NSAccessibilityProgressIndicatorRole;
167+
}
168+
if ((accessibilityTraits & AccessibilityTraits::SearchField) != AccessibilityTraits::None) {
169+
return NSAccessibilityTextFieldRole;
170+
}
171+
if ((accessibilityTraits & AccessibilityTraits::Adjustable) != AccessibilityTraits::None) {
172+
return NSAccessibilitySliderRole;
173+
}
174+
if ((accessibilityTraits & AccessibilityTraits::Header) != AccessibilityTraits::None) {
175+
return NSAccessibilityStaticTextRole;
176+
}
177+
if ((accessibilityTraits & AccessibilityTraits::Switch) != AccessibilityTraits::None) {
178+
return NSAccessibilityCheckBoxRole;
179+
}
180+
if ((accessibilityTraits & AccessibilityTraits::ComboBox) != AccessibilityTraits::None) {
181+
return NSAccessibilityComboBoxRole;
182+
}
183+
if ((accessibilityTraits & AccessibilityTraits::Menu) != AccessibilityTraits::None) {
184+
if ((accessibilityTraits & AccessibilityTraits::Bar) != AccessibilityTraits::None) {
185+
return NSAccessibilityMenuBarRole;
186+
}
187+
if ((accessibilityTraits & AccessibilityTraits::Item) != AccessibilityTraits::None) {
188+
return NSAccessibilityMenuItemRole;
189+
}
190+
return NSAccessibilityMenuRole;
191+
}
192+
if ((accessibilityTraits & AccessibilityTraits::Radio) != AccessibilityTraits::None) {
193+
if ((accessibilityTraits & AccessibilityTraits::Group) != AccessibilityTraits::None) {
194+
return NSAccessibilityRadioGroupRole;
195+
}
196+
return NSAccessibilityRadioButtonRole;
197+
}
198+
if ((accessibilityTraits & AccessibilityTraits::ScrollBar) != AccessibilityTraits::None) {
199+
return NSAccessibilityScrollBarRole;
200+
}
201+
if ((accessibilityTraits & AccessibilityTraits::SpinButton) != AccessibilityTraits::None) {
202+
return NSAccessibilityIncrementorRole;
203+
}
204+
if ((accessibilityTraits & AccessibilityTraits::TabBar) != AccessibilityTraits::None) {
205+
return NSAccessibilityTabGroupRole;
206+
}
207+
if ((accessibilityTraits & AccessibilityTraits::Tab) != AccessibilityTraits::None) {
208+
if ((accessibilityTraits & AccessibilityTraits::List) != AccessibilityTraits::None) {
209+
return NSAccessibilityTabGroupRole;
210+
}
211+
return NSAccessibilityRadioButtonRole;
212+
}
213+
if ((accessibilityTraits & AccessibilityTraits::Disclosure) != AccessibilityTraits::None) {
214+
return NSAccessibilityDisclosureTriangleRole;
215+
}
216+
if ((accessibilityTraits & AccessibilityTraits::Group) != AccessibilityTraits::None) {
217+
return NSAccessibilityGroupRole;
218+
}
219+
if ((accessibilityTraits & AccessibilityTraits::List) != AccessibilityTraits::None) {
220+
return NSAccessibilityListRole;
221+
}
222+
if ((accessibilityTraits & AccessibilityTraits::Table) != AccessibilityTraits::None) {
223+
return NSAccessibilityTableRole;
224+
}
225+
226+
return NSAccessibilityUnknownRole;
227+
};
228+
#endif // macOS]
134229

135230
inline CATransform3D RCTCATransform3DFromTransformMatrix(const facebook::react::Transform &transformMatrix)
136231
{

packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityPrimitives.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,21 @@ enum class AccessibilityTraits : uint32_t {
3434
Header = (1 << 15),
3535
Switch = (1 << 16),
3636
TabBar = (1 << 17),
37+
#if TARGET_OS_OSX // [macOS
38+
ComboBox = (1 << 18),
39+
Menu = (1 << 19),
40+
PopUp = (1 << 20),
41+
Bar = (1 << 21),
42+
Item = (1 << 22),
43+
Group = (1 << 23),
44+
List = (1 << 24),
45+
Tab = (1 << 25),
46+
Table = (1 << 26),
47+
Disclosure = (1 << 27),
48+
Radio = (1 << 28),
49+
ScrollBar = (1 << 29),
50+
SpinButton = (1 << 30),
51+
#endif // macOS]
3752
};
3853

3954
constexpr enum AccessibilityTraits operator|(

0 commit comments

Comments
 (0)