Accessibility
Contrast, focus, touch targets and reduced motion are built into the tokens and components, so they hold for every theme. Labels, alt text and the meaning of your screens are still yours.
Contrast is checked for every theme
The theme generator checks every text and boundary pair in both modes, with WCAG 2 ratios and APCA, and refuses to build a theme that fails. Some of the minimums:
| Foreground | On | Minimum |
|---|---|---|
| color-text-primary | color-background-surface | 7:1 |
| color-text-secondary | color-background-surface | 4.5:1 |
| color-text-tertiary | color-background-surface | 3:1 |
| color-text-on-accent | color-accent | 4.5:1 |
| color-accent, color-focus-ring | color-background-page | 3:1 |
| color-border-control | Page, surface, raised and sunken | 3:1 |
color-text-tertiary meets AA only for large text. Use it for placeholders and timestamps, never for information someone needs to finish a task. The full list is on Colors.
Visible focus
Every interactive component shows a 2px ring in color-focus-ring, 2px away from its edge, on keyboard focus only. For your own focusable elements use focus-visible:focus-ring, and never transition-colors or transition-all, which fade the ring in.
<a href="/settings" className="rounded-element transition-control duration-fast ease-standard focus-visible:focus-ring">
Settings
</a>Touch targets
On touch screens controls reach a 44px target: md, lg and xl grow, and sm controls, checkboxes and icon buttons keep their look but extend their hit area. Text inputs cannot extend theirs, so use Input lg or xl on touch-first screens. Input text is 16px on touch so iOS Safari does not zoom the page.
Never color alone
- A status needs a word or an icon, not just a red or green fill.
- Links are always underlined, because the accent can match the text color.
- Charts with more than four series need direct labels or patterns.
- Disabled controls are also non-interactive (
disabledoraria-disabled), not only gray.
Reduced motion
Movement sits behind motion-safe:. When someone asks for reduced motion, slides and press scaling stop and only fades and color changes remain. Loops such as the Skeleton pulse do not run at all.
<button className="transition-control duration-fast ease-standard motion-safe:active:scale-pressed">Keyboard and screen readers
Overlays, menus, selects, tabs and the other interactive components follow the expected keyboard patterns. Dialogs and sheets move focus inside when they open and return it when they close. Each component spec lists its role and accessibility notes on the component page.
Your part
- Give every field a visible label, with Field and FieldLabel or Label.
- Give every icon-only button an
aria-label(the Button type requires it) and mark decorative iconsaria-hidden. - Write alt text for meaningful images and an empty
altfor decorative ones. - Never make text lighter with opacity; use the secondary or tertiary text tokens.
- Keep one
h1per page and headings in order.
<Button iconOnly aria-label="Close" variant="ghost">
<IconX size={16} aria-hidden />
</Button>