Skip to content

Some accessibilityRole/role have no effect on both iOS and Android #50123

Open

Description

@JoaoMosmann

Description

Some values for the props accessibilityRole and role have no effect on both iOS and Android platforms.
Meaning the screenreader doesn't read the role after the accessibilityLabel.

accessibilityRole

With no effect

On iOS
[
  'alert', 'combobox', 'menu', 'menubar', 'menuitem', 'radio', 'radiogroup', 'scrollbar', 'spinbutton', 'tab',
  'tabbar', 'tablist', 'timer', 'list', 'toolbar',
]
On Android
[
  'tabbar', // Throws error on Android
  'search', 'keyboardkey',
]

With questionable effect

On iOS
[
  'togglebutton', // Gets the Traits value: `Button`, while the 'switch` role gets 2 traits `Button` and `Toggle`. Shouldn't the role togglebutton have the same traits as the 'switch' role?
]

role

With no effect

On iOS
[
  'alert', 'alertdialog', 'application', 'article', 'banner', 'cell', 'columnheader','combobox', 'complementary',
  'contentinfo', 'definition', 'dialog', 'directory', 'document', 'feed', 'figure', 'form', 'grid', 'group',
  'list', 'listitem', 'log', 'main', 'marquee', 'math', 'menu', 'menubar', 'menuitem', 'meter', 'navigation',
  'none', 'note', 'option', 'presentation', 'radiogroup', 'region', 'row', 'rowgroup', 'rowheader', 'scrollbar',
  'searchbox', 'separator', 'slider', 'spinbutton', 'status', 'tab', 'table', 'tablist', 'tabpanel', 'term', 'timer',
  'toolbar', 'tooltip', 'tree', 'treegrid', 'treeitem',
]
On Android
[
  'alertdialog', 'application', 'article', 'banner', 'cell', 'columnheader', 'complementary', 'contentinfo', 'definition', 'dialog',
  'directory', 'document', 'feed', 'figure', 'form', 'group', 'listitem', 'log', 'main', 'marquee', 'math', 'meter', 'navigation',
  'note', 'option', 'presentation', 'region', 'row', 'rowgroup', 'rowheader', 'searchbox', 'separator', 'status', 'table', 'tablist',
  'tabpanel', 'term', 'tooltip', 'tree', 'treegrid', 'treeitem',
]

With questionable effect

On iOS
[
  'radio', // Not questionable, but if the same value is provided on the `accessibilityRole` prop, no effect is taken.
]

Steps to reproduce

  1. Run application either on ios or android yarn ios or yarn android
  2. Enable VoiceOver or TalkBack
  3. Inspect elements which indicates the chosen platform in red
  4. The screen reader will reader only the accessibilityLabel "Item" although it have a role

React Native Version

0.78.0

Affected Platforms

Runtime - Android, Runtime - iOS

Output of npx @react-native-community/cli info

System:
  OS: macOS 15.2
  CPU: (12) arm64 Apple M3 Pro
  Memory: 71.34 MB / 18.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 22.8.0
    path: /opt/homebrew/bin/node
  Yarn: Not Found
  npm:
    version: 10.8.2
    path: /opt/homebrew/bin/npm
  Watchman:
    version: 2024.09.09.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.15.2
    path: /opt/homebrew/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 24.0
      - iOS 18.0
      - macOS 15.0
      - tvOS 18.0
      - visionOS 2.0
      - watchOS 11.0
  Android SDK: Not Found
IDEs:
  Android Studio: 2024.1 AI-241.18034.62.2412.12266719
  Xcode:
    version: 16.0/16A242d
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.12
    path: /usr/bin/javac
  Ruby:
    version: 2.6.10
    path: /usr/bin/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 15.0.1
    wanted: 15.0.1
  react:
    installed: 19.0.0
    wanted: 19.0.0
  react-native:
    installed: 0.78.0
    wanted: 0.78.0
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: true

Stacktrace or Logs

N/A

Reproducer

https://github.com/JoaoMosmann/ReactNativeVoiceOverRolesWithNoEffectReproducer-

Screenshots and Videos

Android Example:
https://github.com/user-attachments/assets/6ca4e808-c571-4758-a484-4d271810f33a

iOS Example:
https://github.com/user-attachments/assets/a5f8b125-eb0e-4420-bbfa-8f1afb5fd901

Whole list:

Image Image Image

Activity

  1. changed the title [-]Some accessibilityRole/role have no effect on both iOS and Android[/-] [+]Some `accessibilityRole`/`role` have no effect on both iOS and Android[/+] on Mar 19, 2025
  2. yanachrnsh commented on May 26, 2025

    @yanachrnsh

    I'm facing same, would be super if you could help to fix it.

  3. a-klotz-p8 commented on Jun 25, 2025

    @a-klotz-p8
    Contributor

    Considering that after 28.06.2025 a lot of companies will require to include accessibility this is something that would be very good to fix asap!
    Or at least the DOCS should include which props work for which Platform.

  4. a-klotz-p8 commented on Jun 25, 2025

    @a-klotz-p8
    Contributor

    This here seems to be the cause. Are there any plans to add Fabric support for the accessibilityRole not supported by UIAccessibilityTrait @NickGerleman? Or am I misinterpreting some old comments here?

  5. kaua-melo commented on Jul 18, 2025

    @kaua-melo

    I'm having the same issue here.
    Seems like it's been there for a while: #43266

  6. douglasjunior commented on Sep 4, 2025

    @douglasjunior

    Seems that tabbar was removed here f39d092

  7. MorganLKestner commented on Oct 10, 2025

    @MorganLKestner

    Bumping for visibility, big accessibility issue.

  8. joevilches commented on Nov 12, 2025

    @joevilches
    Contributor

    Hi, the reason this is happening is many of these web-based roles are not defined on iOS. iOS's role equivalent is UIAccessibilityTrait. @a-klotz-p8 linked the code pointer for the old architecture, but the mapping for the new architecture is defined here, and used by RCTViewComponentView here

    So, for many of these role's defined in JS types, there is just no matching equivalent on the underlying platform. imo, this really was a shortcoming of adding a web-based prop for a platform-specific capability such as screen readers/accessibility.

    The codebase has an example of us working around this here for "checkbox" and "radio" where we just use the accessibilityValue. That is unideal since iOS can mention certain announcements based on the value, that it would not otherwise if some other random string is added in there.

    As a workaround, you can try to put the role string in the accessibilityHint prop, which is meant for supplemental information about the focused component, that does not fit on the label. This might also have risk though, in that certain iOS components have pre-defined hints (see documentation in here), that might be clobbered. But it should be safe to do for generic views.

    I am not sure what, if any, stance RN should take on this problem. If I could wave a magic wand I would go back in time and never add the role prop to begin with, and accept that this is a fundamental difference of web and native that we should not mess with. After all users of VoiceOver are used to the quirks and announcements that VoiceOver provides, and taking an opinion on that might be confusing. I think its a bad idea for us to extend the hacks we are doing for radio and checkbox for all the remaining missing roles, but maybe there is a safe way to do that

  9. react-native-bot commented on May 12, 2026

    @react-native-bot
    Collaborator

    This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

  10. added
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    on May 12, 2026
  11. florismettey commented on May 12, 2026

    @florismettey

    The issue is still present en last React Native version. Maybe we should at least update the doc and remove not working properties

  12. removed
    StaleThere has been a lack of activity on this issue and it may be closed soon.
    on May 13, 2026
  13. abdelouali commented on Oct 26, 2026

    @abdelouali

    Still reproducible on iOS with the New Architecture (Fabric).

    Versions

    App: React Native 0.83.10, tested on the iPhone 17 Pro simulator (iOS 26.5) with the Accessibility Inspector
    Source checked: 0.88.0 and main. Both still map tab and tablist to UIAccessibilityTraitNone, in RCTViewManager.m and in Fabric’s accessibilityPropsConversions.h. On main, Role::Tab is now treated as interactive in RCTViewComponentView.mm, but VoiceOver still doesn’t announce it.

    What we tried for a custom horizontal tab list (ScrollView > Pressable items with accessibilityState={{ selected }}):

    accessibilityRole="tablist" on the container and "tab" on the items: VoiceOver reads only the label and “selected”, no role.
    accessibilityRole="tabbar" on the ScrollView: no change.
    accessibilityRole="tabbar" on a View that is the direct parent of the items: no change.
    tabbar on that parent View plus accessibilityRole="button" on the items (the same structure as a native UITabBar): VoiceOver reads “button”, never “tab, 1 of 2”.

    Workaround we shipped: on iOS, we put the role and position in accessibilityValue:

    accessibilityLabel={label}
    accessibilityRole="tab"
    accessibilityValue={
    Platform.OS === 'ios'
    ? { text: tab ${index + 1} of ${count} }
    : undefined
    }

    VoiceOver then reads “Messages, tab 1 of 2, selected”, and the accessible name stays clean. RN already does the same for checkbox and radio in RCTViewComponentView’s accessibilityValue getter, adding a localized role string. Doing that for tab, for example “tab, X of Y” when the parent has the tablist role, would fix this without any workaround in apps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions