react-native icon indicating copy to clipboard operation
react-native copied to clipboard

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

Open JoaoMosmann opened this issue 10 months ago • 1 comments

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

JoaoMosmann avatar Mar 19 '25 10:03 JoaoMosmann

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

yanachrnsh avatar May 26 '25 13:05 yanachrnsh

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.

a-klotz-p8 avatar Jun 25 '25 08:06 a-klotz-p8

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?

a-klotz-p8 avatar Jun 25 '25 14:06 a-klotz-p8

I'm having the same issue here. Seems like it's been there for a while: https://github.com/facebook/react-native/issues/43266

kaua-melo avatar Jul 18 '25 09:07 kaua-melo

Seems that tabbar was removed here https://github.com/facebook/react-native/commit/f39d0923c78686118a5d268c0e659d2608d28df0

douglasjunior avatar Sep 04 '25 15:09 douglasjunior

Bumping for visibility, big accessibility issue.

MorganLKestner avatar Oct 10 '25 14:10 MorganLKestner

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

joevilches avatar Nov 12 '25 17:11 joevilches