[iOS][New Architecture] VoiceOver never announces "collapsed" for aria-expanded={false} (regression from RCTView)
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 84/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- ios, objective-c, react-native
- Área
- accessibility, mobile
Línea de trabajo
Comienza en RCTViewComponentView.mm, donde accessibilityState.expanded se convierte en el valor de VoiceOver, y compáralo con el manejo del estado expanded en React/Views/RCTView.m. Ejecuta el Snack enlazado con VoiceOver en iOS y verifica que los estados expanded false se anuncien como "collapsed", mientras que los estados true y checked sigan siendo correctos.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Description
On iOS with the New Architecture, an element with aria-expanded={false}, or accessibilityState={{ expanded: false }}, is announced by VoiceOver with no state. For example, an accordion header built as <Pressable role="button" aria-expanded={false}> is read as "Returns, button". Once expanded it is read as "expanded", which works. A VoiceOver user cannot tell a collapsed section from an ordinary button.
The cause is in RCTViewComponentView.mm, where the accessibility value is built from the accessibility state:
if (accessibilityState.expanded.value_or(false)) {
[valueComponents
addObject:RCTLocalizedString("expanded", "a menu, dialog, accordian panel, or other widget which is expanded")];
}
There is no branch for expanded == false. The code directly above it handles both values of checked, adding "checked" and "unchecked".
This is a regression from the old architecture. React/Views/RCTView.m announces both states:
[valueComponents addObject:rolesAndStatesDescription[[val boolValue] ? @"expanded" : @"collapsed"]];
The localised "collapsed" string already exists there, with the description "a menu, dialog, accordian panel, or other widget which is collapsed".
I checked the source of 0.81.0, 0.86.3, 0.87.1 and main at commit a4085264df (29 September 2026). All four have the Fabric code above. Android is not affected: TalkBack announces "collapsed".
Suggested fix, in RCTViewComponentView.mm:
if (accessibilityState.expanded.has_value()) {
[valueComponents
addObject:accessibilityState.expanded.value()
? RCTLocalizedString("expanded", "a menu, dialog, accordian panel, or other widget which is expanded")
: RCTLocalizedString("collapsed", "a menu, dialog, accordian panel, or other widget which is collapsed")];
}
Until then, apps can work around it on iOS by supplying the word as the accessibility value. The name stays unchanged:
<Pressable
role="button"
aria-expanded={open}
accessibilityValue={Platform.OS === 'ios' && !open ? { text: 'collapsed' } : undefined}
>
VoiceOver output on the device:
role="checkbox",aria-checked={false}(control, same code path): "Email me offers, checkbox, unchecked". The false state is announced.role="button",aria-expanded={false}: "Returns, button". No state.role="button",aria-expanded={true}: "Returns, expanded, button". Works.accessibilityRole="button",accessibilityState={{ expanded: false }}: "Delivery, button". No state.- With the workaround above: "Warranty, collapsed, button".
Expected: "collapsed" is announced for expanded: false, as it was with the old architecture and as TalkBack does.
Steps to reproduce
- Open the Snack below on an iPhone with VoiceOver on. Snack runs the New Architecture.
- Swipe to "Email me offers". VoiceOver says "unchecked". This is the control.
- Swipe to "Returns". VoiceOver says "Returns, button", with no state.
- Double-tap "Returns". VoiceOver says "expanded".
- Swipe to "Delivery". VoiceOver says "Delivery, button", with no state.
- Swipe to "Warranty", which uses the workaround. VoiceOver says "Warranty, collapsed, button".
React Native Version
0.86.3
Affected Platforms
Runtime - iOS
Output of npx @react-native-community/cli info
System:
OS: Windows 11 10.0.26200
CPU: (14) x64 Intel(R) Core(TM) Ultra 7 155U
Memory: 17.80 GB / 31.52 GB
Binaries:
Node: 24.15.0
npm: 11.12.1
npmPackages:
react: 19.2.3
react-native: 0.86.3
Run in Expo Go on Expo SDK 57, which uses the New Architecture.
Device: iPhone Air, iOS 26.7.
Stacktrace or Logs
No crash or error. This is an accessibility output bug. The VoiceOver output for each element is under Description.
MANDATORY Reproducer
https://snack.expo.dev/@saleeem4rahman/voiceover-collapsed-state-missing
Snack runs Expo SDK 54 (React Native 0.81). The VoiceOver output above was recorded on 0.86.3 with the same props, and the 0.81 source has the same code.
Screenshots and Videos
None. The behaviour is audible, not visible.
- Lenguaje dominante
- C++
- Estrellas
- 127k
- Forks
- 25.3k
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de react/react-native
-
[Android] Unrecognized fontFamily silently falls back to the system font (no log, unlike iOS)AbiertoNeeds: Triage :mag: Platform: Android Platform: iOS
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
react/react-native#58750 ·
Los mantenedores suelen responder en 1 día
-
Needs: Author Feedback Needs: Repro
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
react/react-native#58659 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
Needs: Author Feedback Needs: Repro
Dificultad 1/5 Menos de una hora Aptitud para principiantes 92/100
react/react-native#58621 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Needs: Author Feedback Needs: Repro
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
react/react-native#58610 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Needs: Triage :mag:
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
react/react-native#58565 · 1 comentario · 2 reacciones ·
Los mantenedores suelen responder en 1 día
Todos los issues de react/react-native
Issues similares
-
Broken links in the docsAbierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 85/100
microsoft/onnxruntime#33018 ·
Los mantenedores suelen responder en 2 días
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día
-
DataLakeFileSystemClient::ListPaths() throws JSON exception due to accessing undefined fieldsAbiertocustomer-reported needs-triage question
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Azure/azure-sdk-for-cpp#7435 ·
Los mantenedores suelen responder en 1 día
-
ChromieCraft Generic Confirmed World Event
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
azerothcore/azerothcore-wotlk#27882 ·
Los mantenedores suelen responder en 1 día
-
MacOS build failureAbiertobug
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
aristocratos/btop#1874 ·
Los mantenedores suelen responder en 1 día