Accessibility
Accessibility is not a feature you opt into here — it's the reason these primitives exist. Every component implements an established interaction pattern so you don't have to wire up ARIA, keyboard handling, and focus management yourself.
WAI-ARIA patterns
Components follow the WAI-ARIA Authoring Practices for their role: menus use the menu button pattern, tabs use the tabs pattern, listboxes and comboboxes follow the combobox pattern, and so on. Roles, states, and relationships (aria-expanded, aria-selected, aria-controls, aria-labelledby, …) are wired for you and kept in sync with the component's state.
Keyboard support
Full keyboard operation is built in:
- Roving focus for composite widgets (tabs, toggle groups, menus, trees, grids) — arrow keys move between items,
Home/Endjump to the ends. - Typeahead in list-style components, so typing focuses the matching option.
- Activation semantics that match the platform:
Enter/Spacewhere expected,Escapeto dismiss overlays,Tabto move on. - Directional open/close for nested structures like submenus (
ArrowRight/ArrowLeft).
Focus management
- Overlays (dialog, popover, menu) manage focus on open and return focus to the trigger on close.
- A layer stack ensures only the topmost overlay responds to
Escapeand outside interaction, so nested overlays close in the right order. - Focus is modality-aware: components expose
data-focus-visibleso you can show focus rings for keyboard users without lighting them up on mouse clicks.
SSR-safe by default
Default selection, expansion, and open states are resolved on the server, so the first paint is correct and there's no flash or focus jump during hydration.
Verify it yourself
Every component ships with tests that exercise its accessibility contract in a real browser. Each component page also documents the exact roles and data attributes it emits, so you can audit the output against your own requirements.