RoadieRoadie
  • Home
  • Brand
  • Foundations
  • Content
  • Tokens
  • Components
  • Charts
  • Widgets
  • Appearance
HomeBrandFoundations
Appearance

Foundations

  • Visual

    • Colors
    • Elevation
    • Iconography
    • Shape
    • Theming
  • Content

    • Date and time
    • Layout
    • Prose styles
    • Typography
  • Behaviour

    • Accessibility
    • Interactions
    • Motion
    • View transitions
  • Building apps

    • Forms
    • Linking
    • Navigation
    • Performance
    • Records modelAlpha
    • Tables

Accessibility

Docs updated
11 Oct 2026

ReferenceEmphasis and states tokens

Accessibility is not a feature. It's a quality bar. HTML is the accessible baseline, and browsers provide accessibility for free if you use semantic elements.

Semantic HTML first

If you use a <div> for a button, you have to rebuild 20 years of browser engineering yourself. Use the right element and get keyboard, focus, and screen reader support for free.

Use native elements

Native elements carry semantics, keyboard behaviour, and ARIA roles automatically.

<button onClick={handleSave}>Save</button>
<a href="/settings">Settings</a>
<nav aria-label="Main">…</nav>
<main>…</main>

Do

Use <button> for actions, <a> for navigation, <nav> and <main> for landmarks, and <article> for self-contained content.

<div onClick={handleSave} className="btn">Save</div>
<span onClick={() => navigate('/settings')}>Settings</span>

Don’t

Use <div> or <span> with click handlers to create custom buttons or links. You lose keyboard support, focus management, and screen reader announcements.

Meaningful document structure

Heading hierarchy is the table of contents for screen reader users.

Do

Use headings in order, <h1>, then <h2>, then <h3>. Don't skip levels. Every page should have exactly one <h1>.

Don’t

Choose heading levels based on visual size. Use <h4> after <h2> because it looks right. Use the text-display-* classes for visual sizing instead.

ARIA as a last resort

The first rule of ARIA is don't use ARIA. If a native HTML element with the semantics you need exists, use it. ARIA supplements HTML, and it doesn't replace it.

Prefer native over ARIA

ARIA overrides native semantics. Used incorrectly, it makes things worse, not better.

<!-- Native checkbox gets keyboard, focus and state for free -->
<input type="checkbox" id="terms" />
<label htmlFor="terms">I agree to the terms</label>

Do

Reach for ARIA only when there is no native element for the pattern, such as tabs, tree views, and comboboxes. Roadie's Base UI components handle ARIA attributes automatically for these cases.

<!-- Reinventing a checkbox from scratch -->
<div role="checkbox" aria-checked="false"
tabIndex={0} onClick={toggle}
onKeyDown={handleKeyDown}>
I agree to the terms
</div>

Don’t

Build custom ARIA widgets when a native element exists. Every attribute you add manually is an attribute you must maintain.

Colour and contrast

Sufficient contrast is non-negotiable. Never convey meaning through colour alone. See Colors for the full colour system.

Meet the APCA contrast thresholds

Roadie measures all contrast with APCA, not WCAG 2 ratios. The thresholds for body text, labels, large text, and non-text UI are in Colors.

Do

Use Roadie's semantic text colours (text-normal, text-subtle, text-strong), and check the one you pick against the threshold for its role and surface.

Don’t

Use raw colour values without checking contrast. Light grey text on a white background may look subtle but fails APCA.

Colour is not the only signal

Many colour-blind users can't tell red from green. Always pair colour with another indicator.

Do

Pair colour with icons, text labels, or patterns. An error state uses intent-danger (red) plus an error icon plus error text.

Don’t

Indicate success or failure only through green or red colouring with no supporting text or icon.

Keyboard and focus

Keyboard accessibility is covered in depth in the Interactions foundation. It covers keyboard operability, visible focus indicators, focus management, and hit targets.

Reduced motion

Motion can cause nausea and disorientation. Roadie includes a global prefers-reduced-motion reset. See Motion for full details on duration tokens, easing, and how to test.

Screen readers

Screen readers interpret the DOM, not the pixels. What you see is not what they hear.

Meaningful alt text

Images without alt text are invisible to screen readers. Decorative images need empty alt.

<!-- Informative image -->
<img src="seating-map.png" alt="Venue seating map showing sections A through F" />
<!-- Decorative image -->
<img src="divider.svg" alt="" />

Do

Write alt text that describes the content or function of the image, not its appearance. Use empty alt="" for purely decorative images.

Don’t

Omit the alt attribute entirely, so screen readers read the filename, or write "image" as alt text.

Announce dynamic content

Screen readers don't automatically notice DOM changes. Tell them what changed.

<!-- Announce status updates -->
<div role="status" aria-live="polite">
3 items added to cart
</div>
<!-- Announce urgent errors -->

Do

Use aria-live="polite" for non-urgent updates, such as status messages and search results. Use role="alert" for urgent notifications, such as errors and warnings.

Don’t

Update content silently. A toast notification that isn't announced leaves screen reader users unaware of what happened.

Forms

Form interaction patterns, such as labels, placeholders, validation, and submit behaviour, are covered in Interactions and Forms. This section covers the attributes that make forms accessible to assistive technology, which Field and Fieldset set for you.

Associate errors with fields

Screen readers need a programmatic link between an input and its error message.

<Field invalid={hasError}>
<Field.Label>Email</Field.Label>
<Field.Input type='email' />
<Field.ErrorText>Enter a valid email address</Field.ErrorText>
</Field>

Do

Wrap the control in Field and set invalid. Field marks the control aria-invalid, links Field.ErrorText to it with aria-describedby, and announces the error.

Don’t

Show a red border and error text next to a field without any programmatic association. Sighted users see it. Screen reader users don't.

Group related fields

Field groups need a shared label so screen readers announce the context.

<Fieldset>
<Fieldset.Legend>Billing address</Fieldset.Legend>
<Field>
<Field.Label>Street</Field.Label>
<Field.Input />
</Field>

Do

Use Fieldset and Fieldset.Legend, which render <fieldset> and <legend>, to group related fields. Screen readers announce the legend before each field in the group.

Don’t

Group fields under a visual heading with no programmatic relationship. Screen reader users won't know the fields are related.

What Roadie handles

The design system provides accessible primitives. You get these for free when you use Roadie components.

PrimitiveWhat you get
Base UI primitivesComponents built on Base UI provide correct ARIA attributes, focus management, and keyboard navigation out of the box.
Focus ringsThe base styles draw a :focus-visible ring on links and buttons, coloured by the nearest intent. is-interactive animates it in.
Field state stylingis-interactive-field provides visual state transitions for focus and aria-invalid automatically.
Contrast-safe tokensSemantic colour tokens (text-normal, text-subtle) adapt to light and dark modes. Check each against the APCA threshold for its role and surface.

Testing checklist

Run through this checklist before shipping. Automated tools catch about 30% of issues, and the rest need manual testing.

TestHowWhat to check
KeyboardTab through the pageEvery interactive element is reachable and operable. Focus order is logical. There are no keyboard traps.
Screen readerVoiceOver (macOS) or NVDA (Windows)Content is announced meaningfully. Dynamic updates are heard. Form errors are associated.
ContrastAn APCA contrast checkerText, labels, and UI components meet the APCA thresholds in Colors.
Reduced motionIn DevTools, open Rendering and emulate prefers-reduced-motionNo animations play. No functionality is lost.
ZoomBrowser zoom to 200%No content is clipped or overlapping. Layout reflows gracefully.
Previous page← TypographyNext pageInteractions →