From dceed2a658c645a2255c8ac5207721d367d70fa4 Mon Sep 17 00:00:00 2001 From: lazerg Date: Tue, 29 Sep 2026 21:03:47 +0500 Subject: [PATCH] Announce collapsed state for expanded: false on iOS --- .../View/RCTViewComponentView.mm | 4 +++ .../Mounting/RCTViewComponentViewTests.mm | 33 +++++++++++++++++++ 2 files changed, 37 insertions(+) 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 61ef98f921cd..41603be22939 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -1618,6 +1618,10 @@ - (NSString *)accessibilityValue [valueComponents addObject:RCTLocalizedString("expanded", "a menu, dialog, accordian panel, or other widget which is expanded")]; } + if (!accessibilityState.expanded.value_or(true)) { + [valueComponents addObject:RCTLocalizedString( + "collapsed", "a menu, dialog, accordian panel, or other widget which is collapsed")]; + } if (accessibilityState.busy) { [valueComponents addObject:RCTLocalizedString("busy", "an element currently being updated or modified")]; diff --git a/packages/react-native/React/Tests/Mounting/RCTViewComponentViewTests.mm b/packages/react-native/React/Tests/Mounting/RCTViewComponentViewTests.mm index 91e100d28df1..1a5e58d91cd1 100644 --- a/packages/react-native/React/Tests/Mounting/RCTViewComponentViewTests.mm +++ b/packages/react-native/React/Tests/Mounting/RCTViewComponentViewTests.mm @@ -238,6 +238,39 @@ - (void)testViewWithoutRoleIsNotKeyboardFocusable XCTAssertFalse(view.canBecomeFocused); } +#pragma mark - accessibilityValue for expanded state + +static RCTViewComponentView *makeViewWithExpandedState(std::optional expanded) +{ + RCTViewComponentView *view = [RCTViewComponentView new]; + auto props = std::make_shared(); + props->accessible = true; + props->accessibilityRole = "button"; + AccessibilityState accessibilityState; + accessibilityState.expanded = expanded; + props->accessibilityState = accessibilityState; + [view updateProps:props oldProps:ViewShadowNode::defaultSharedProps()]; + return view; +} + +- (void)testAccessibilityValueAnnouncesExpanded +{ + RCTViewComponentView *view = makeViewWithExpandedState(true); + XCTAssertEqualObjects(view.accessibilityValue, @"expanded"); +} + +- (void)testAccessibilityValueAnnouncesCollapsed +{ + RCTViewComponentView *view = makeViewWithExpandedState(false); + XCTAssertEqualObjects(view.accessibilityValue, @"collapsed"); +} + +- (void)testAccessibilityValueIsNilWithoutExpandedState +{ + RCTViewComponentView *view = makeViewWithExpandedState(std::nullopt); + XCTAssertNil(view.accessibilityValue); +} + #pragma mark - outline style on square corners (#57841) static RCTViewComponentView *makeViewWithOutlineStyle(OutlineStyle outlineStyle)