Accessibility
The conformance target this design system holds itself to, the contrast and keyboard requirements that follow from it, and how the system reports its own open findings.
The standard
Every component in this system is measured against WCAG 2.2, Level AA. That is the target for the components themselves and for any page assembled from them.
A conformance target is a bar, not a badge. This system publishes its own validation results, and the report is expected to show open findings at any given time. A component with a live finding is a component that has been measured, not one that has been excused. The rule is that findings are visible, tracked and closed, never suppressed to make a report look clean.
Automated tooling catches roughly a third of WCAG failures. The rest needs a person with a keyboard and a screen reader.
Contrast
Text has to clear these ratios against its own background:
| Content | Minimum ratio |
|---|---|
| Body text (under 18px, or under 14px bold) | 4.5:1 |
| Large text (18px and above, or 14px bold and above) | 3:1 |
| Icons, borders and other non-text UI | 3:1 |
| Disabled controls | No requirement, but avoid relying on them to convey state |
Practical consequences:
- A colour that passes at heading size can fail at body size. Check the pairing at the size it is actually used.
- Accent colours chosen for brightness are the usual source of failures. Bright yellows and mid greens rarely clear 4.5:1 on white.
- Never fix contrast by making the text bigger unless the design genuinely calls for larger text.
- Colour is never the only carrier of meaning. Pair it with a label, an icon or a shape.
Keyboard access
Everything operable by mouse has to be operable by keyboard.
TabandShift+Tabreach every interactive element in a sensible order.Enteractivates links,EnterandSpaceactivate buttons.Escapedismisses anything layered over the page.- Arrow keys move within a composite widget such as tabs or a menu.
- Focus is always visible. Never remove an outline without replacing it.
Two traps show up repeatedly:
- Scrollable regions. A container that scrolls but holds no focusable child is
unreachable by keyboard. Give it
tabindex="0"and an accessible name so it can be scrolled with arrow keys. - Focus escaping a dialog. When a modal opens, focus moves into it and stays there until it closes, then returns to the trigger.
Semantics
- Use the element that means what you want.
<button>for actions,<a href>for navigation. A<div>with a click handler is neither. - One
<h1>per page, and no skipped heading levels. - Landmarks on every page:
<header>,<nav>,<main>,<footer>. Give a uniquearia-labelto a landmark that appears more than once. - A skip link is the first focusable element on the page.
- ARIA is a last resort. Native semantics are correct by default and cannot fall out of sync.
Images and icons
1<!-- Meaningful image: describe what it conveys -->
2<img src="chart.png" alt="Revenue rising from 40 to 65 percent across four quarters">
3
4<!-- Decorative image: empty alt removes it from the accessibility tree -->
5<img src="pattern.svg" alt="">
6
7<!-- Icon beside text: the text is the label -->
8<svg aria-hidden="true" focusable="false">…</svg>
9
10<!-- Icon-only control: label the control, not the icon -->
11<button type="button" aria-label="Close">
12 <svg aria-hidden="true" focusable="false">…</svg>
13</button>Forms
- Every input has a visible
<label>tied to it byforandid. - Placeholder text is not a label. It disappears on focus and often fails contrast.
- Error messages sit next to the field, describe the fix, and are linked with
aria-describedby. - Required fields are marked in text, not only with a coloured asterisk.
Motion and timing
- Respect
prefers-reduced-motionfor anything that moves, parallaxes or autoplays. - Content that animates in must still be present when animation is suppressed.
- Nothing flashes more than three times per second.
- Carousels and auto-advancing content need a pause control.
Review checklist
Run this before a component is considered done:
- Tab through it. Everything reachable, focus always visible, order matches the visual layout.
- Zoom to 200%. No content lost, no horizontal scroll.
- Turn off colour. Every state still readable.
- Run an automated scan and read the findings rather than the score.
- Listen to it once with a screen reader. VoiceOver on macOS or NVDA on Windows.
Tools
| Tool | Use |
|---|---|
| axe DevTools | Automated rule scan in the browser |
| WebAIM Contrast Checker | Checking a single colour pairing |
| NVDA / VoiceOver | Screen reader testing |
| Keyboard only | The cheapest test, and the one that finds the most |