Accessibility
How components handle roles, focus, keyboard, contrast and reduced motion.Accessibility is part of each component’s definition of done. Every component page documents its strategy; this page summarises the shared rules.
Semantics
- Native elements on web (
button,input,label,h1–h6) and ARIA roles on native (role,aria-*props map to iOS/Android accessibility APIs). - Icons are decorative by default; icon-only buttons require
aria-labelat the type level. - Composite widgets follow the WAI-ARIA Authoring Practices (tabs, radio group, dialog, listbox).
Keyboard & focus
- Visible 2px focus ring using the theme
ringcolor, shown only for keyboard focus (:focus-visible). - Dialogs trap focus, restore it to the trigger and close on Escape.
- Tooltips open on keyboard focus as well as hover and dismiss with Escape.
Contrast
Theme generation enforces WCAG 2.x AA (4.5:1) for every text/background pair and 3:1 for focus rings — including custom brand colors. The test suite checks all presets in light and dark mode.
Reduced motion
When the OS asks for reduced motion, CSS transitions are removed on web and components skip animations on native (useReducedMotion()). Progress indicators keep moving slowly because they convey state.
Touch targets
On iOS/Android, buttons extend their pressable area with hitSlop to reach 44pt; list items in sheets grow to 44pt on touch devices.
How we test
Unit tests query by role and accessible name (Testing Library), exercise keyboard interaction and assert ARIA state. Tests caught — and we fixed — a Tamagui Dialog.Close label override and a tooltip that did not open on keyboard focus.