Skip to content

Commit 0ade23d

Browse files
joevilchesfacebook-github-bot
authored andcommitted
accessibleElements impl on iOS (#49582)
Summary: Pull Request resolved: #49582 TSIA, this is a fairly straightforward implementation since iOS likes the shape the data is already in. Note I form a stacking context since I need the native view that has `accessibilityElements` to actually be an ancestor of everything under it Note I am not exposing anything yet on the JS side, since we need to do Android also Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D69625269 fbshipit-source-id: 836f1bb631646408a5726f126be61c0ff6afe1d0
1 parent 99f9626 commit 0ade23d

File tree

4 files changed

+39
-1
lines changed

4 files changed

+39
-1
lines changed

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#import <React/RCTConversions.h>
1919
#import <React/RCTLinearGradient.h>
2020
#import <React/RCTLocalizedString.h>
21+
#import <React/RCTViewFinder.h>
2122
#import <react/featureflags/ReactNativeFeatureFlags.h>
2223
#import <react/renderer/components/view/ViewComponentDescriptor.h>
2324
#import <react/renderer/components/view/ViewEventEmitter.h>
@@ -48,6 +49,7 @@ @implementation RCTViewComponentView {
4849
NSSet<NSString *> *_Nullable _propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN;
4950
UIView *_containerView;
5051
BOOL _useCustomContainerView;
52+
NSMutableArray<NSString *> *_accessibleElementsNativeIds;
5153
}
5254

5355
#ifdef RCT_DYNAMIC_FRAMEWORKS
@@ -389,6 +391,13 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
389391
}
390392
}
391393

394+
if (oldViewProps.accessibilityElements != newViewProps.accessibilityElements) {
395+
_accessibleElementsNativeIds = [NSMutableArray new];
396+
for (const std::string &childId : newViewProps.accessibilityElements) {
397+
[_accessibleElementsNativeIds addObject:RCTNSStringFromString(childId)];
398+
}
399+
}
400+
392401
// `accessibilityTraits`
393402
if (oldViewProps.accessibilityTraits != newViewProps.accessibilityTraits) {
394403
self.accessibilityElement.accessibilityTraits =
@@ -595,6 +604,23 @@ - (void)prepareForRecycle
595604
_reactSubviews = [NSMutableArray new];
596605
}
597606

607+
- (NSArray<NSObject *> *)accessibilityElements
608+
{
609+
if ([_accessibleElementsNativeIds count] <= 0) {
610+
return super.accessibilityElements;
611+
}
612+
613+
NSMutableArray<UIView *> *elements = [NSMutableArray new];
614+
for (NSString *childId : _accessibleElementsNativeIds) {
615+
UIView *viewWithMatchingNativeId = [RCTViewFinder findView:self withNativeId:childId];
616+
if (viewWithMatchingNativeId) {
617+
[elements addObject:viewWithMatchingNativeId];
618+
}
619+
}
620+
621+
return elements;
622+
}
623+
598624
- (void)setPropKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN:(NSSet<NSString *> *_Nullable)props
599625
{
600626
_propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN = props;

packages/react-native/ReactCommon/react/renderer/components/view/AccessibilityProps.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,15 @@ AccessibilityProps::AccessibilityProps(
4646
"accessibilityLabel",
4747
sourceProps.accessibilityLabel,
4848
"")),
49+
accessibilityElements(
50+
ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
51+
? sourceProps.accessibilityElements
52+
: convertRawProp(
53+
context,
54+
rawProps,
55+
"accessibilityElements",
56+
sourceProps.accessibilityElements,
57+
{})),
4958
accessibilityLabelledBy(
5059
ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
5160
? sourceProps.accessibilityLabelledBy
@@ -246,6 +255,7 @@ void AccessibilityProps::setProp(
246255
RAW_SET_PROP_SWITCH_CASE_BASIC(accessible);
247256
RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityState);
248257
RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLabel);
258+
RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityElements);
249259
RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLabelledBy);
250260
RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityHint);
251261
RAW_SET_PROP_SWITCH_CASE_BASIC(accessibilityLanguage);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class AccessibilityProps {
3434
bool accessible{false};
3535
std::optional<AccessibilityState> accessibilityState{std::nullopt};
3636
std::string accessibilityLabel{""};
37+
std::vector<std::string> accessibilityElements{};
3738
AccessibilityLabelledBy accessibilityLabelledBy{};
3839
AccessibilityLiveRegion accessibilityLiveRegion{
3940
AccessibilityLiveRegion::None};

packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ void ViewShadowNode::initialize() noexcept {
6262
!viewProps.filter.empty() ||
6363
viewProps.mixBlendMode != BlendMode::Normal ||
6464
viewProps.isolation == Isolation::Isolate ||
65-
HostPlatformViewTraitsInitializer::formsStackingContext(viewProps);
65+
HostPlatformViewTraitsInitializer::formsStackingContext(viewProps) ||
66+
!viewProps.accessibilityElements.empty();
6667

6768
bool formsView = formsStackingContext ||
6869
isColorMeaningful(viewProps.backgroundColor) || hasBorder() ||

0 commit comments

Comments
 (0)