Skip to content

Accessibility

ARIA is the vocabulary. React Native has supported the role prop since 0.71, so a single role="switch" means the same thing to both backends; accessibilityRole is still accepted and mapped where the two differ (header → heading, search → searchbox, image → img, adjustable → slider).

The role table is generated from aria-query — the machine-readable ARIA specification that eslint-plugin-jsx-a11y and Testing Library read — rather than hand-kept, so it cannot quietly drift. With it the compiler can say more than “that is not a role”:

  • an abstract role (role="widget") is named as one, not rejected as unknown
  • a role used without the states or properties it is meaningless without is reported as an incomplete pattern
  • a role with no Web equivalent is reported rather than silently dropped

@hozo/behaviors carries the headless primitives that need real runtime behaviour — focus management, keyboard handling, floating positioning, and hover delay groups.

Every Storybook story is continuously checked against axe-core in CI, catching automated regressions in contrast, structural ARIA syntax, and roles with zero violations. Real screen readers read part of it weekly: NVDA and VoiceOver over the Storybook patterns, and TalkBack over the Native demo app’s controls. iOS VoiceOver is not automated. Full conformance still requires manual screen reader testing.