Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

[iOS][New Architecture] VoiceOver never announces "collapsed" for aria-expanded={false} (regression from RCTView)

Fermée Adaptée aux débutants
#58,746 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
2/5
Temps estimé
1-3 heures
Accessibilité débutants
84/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
ios, objective-c, react-native

Piste de recherche

Commencez dans RCTViewComponentView.mm, où accessibilityState.expanded est converti en la valeur VoiceOver, et comparez-le avec la gestion de l’état expanded dans React/Views/RCTView.m. Exécutez le Snack lié avec VoiceOver sur iOS et vérifiez que les états expanded false sont annoncés comme "collapsed", tandis que les états true et checked restent corrects.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

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
  1. Open the Snack below on an iPhone with VoiceOver on. Snack runs the New Architecture.
  2. Swipe to "Email me offers". VoiceOver says "unchecked". This is the control.
  3. Swipe to "Returns". VoiceOver says "Returns, button", with no state.
  4. Double-tap "Returns". VoiceOver says "expanded".
  5. Swipe to "Delivery". VoiceOver says "Delivery, button", with no state.
  6. 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.

Langage dominant
C++
Étoiles
127k
Forks
25.3k
Métriques de merge des PR
Aucune PR mergée en 30 j

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de react/react-native

Toutes les issues de react/react-native

Issues similaires

Plus d'issues C++

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.