Design System Tokens & Component Contracts
Permalink to "Design System Tokens & Component Contracts"A design system is the single most leveraged place to do accessibility work in a data product organisation. A focus token fixed once fixes every grid, chart and form. A required label prop names every table built afterwards. A keyboard contract written once becomes documentation, help dialogs and tests for every product. Equally, a design system with an inaccessible default spreads that failure everywhere: a compact density with 14-pixel checkboxes, a focus ring that vanishes on selected rows, an optional name that nobody sets.
This topic covers the foundations that decide whether products built with a design system are accessible by default: component APIs (props), tokens (density and focus), contracts (keyboard behaviour) and the process for changing them (deprecation). The users affected are every user of every product built on the system. The people affected inside the organisation are design system maintainers, who own the foundations, and product teams, who inherit them. The failure this topic prevents is a design system that is “accessible” in its own documentation and inaccessible in production, because the accessible path required extra effort that teams did not spend.
This topic belongs to accessible data component libraries.
WCAG criteria in scope
Permalink to "WCAG criteria in scope"| Criterion | Level | Foundation that addresses it |
|---|---|---|
| 1.3.1 Info and Relationships | A | Row header props; structured components |
| 1.4.11 Non-text Contrast | AA | Focus and selection tokens |
| 1.4.12 Text Spacing | AA | Density tokens with minimum heights |
| 2.1.1 Keyboard | A | Keyboard contracts; deprecating mouse-only APIs |
| 2.4.7 / 2.4.11 Focus | AA | Focus tokens; sticky-aware layouts |
| 2.5.8 Target Size (Minimum) | AA | Density tokens with target minimums |
| 4.1.2 Name, Role, Value | A | Required name props |
| 4.1.3 Status Messages | AA | Message props and announcer integration |
Prerequisites
Permalink to "Prerequisites"- Familiarity with the component patterns on this site, especially composite widget roles & states.
- Visual testing from visual regression & theme testing.
- Governance practices from accessibility governance for data products.
ARIA & HTML spec reference
Permalink to "ARIA & HTML spec reference"| Foundation | What it encodes | Example |
|---|---|---|
| Name props | aria-label / aria-labelledby on the right element |
label or labelledBy required |
| Row header prop | th scope="row" or rowheader |
rowHeader: 'id' |
| Message props | role="status" content |
messages.sorted() |
| Focus tokens | :focus-visible outline |
two-tone ring |
| Density tokens | min heights; target minimums | targetMin: 24px |
| Contract data | keys, focus, announcements | gridContract.contexts |
| Deprecations | API lifecycle | @deprecated with WCAG note |
Step-by-step implementation
Permalink to "Step-by-step implementation"Step 1 — Accessibility props
Permalink to "Step 1 — Accessibility props"type GridProps = ({ label: string } | { labelledBy: string }) & { rowHeader: string; messages?: GridMessages };
See designing accessibility props for grid components.
Step 2 — Density tokens
Permalink to "Step 2 — Density tokens"{ "compact": { "rowMinHeight": "32px", "targetMin": "24px" } }
See density tokens and target size in data grids.
Step 3 — Focus tokens
Permalink to "Step 3 — Focus tokens":focus-visible { outline: 2px solid var(--focus-inner); box-shadow: 0 0 0 6px var(--focus-outer); }
See focus ring tokens across themes.
Step 4 — Keyboard contracts
Permalink to "Step 4 — Keyboard contracts"export const gridContract = { version: '4.2', contexts: { navigation: [ … ] } };
See documenting keyboard contracts for components.
Step 5 — Deprecations
Permalink to "Step 5 — Deprecations"/** @deprecated since 5.2 — fails SC 2.1.1. Use rowAction. Removed in 6.0. */ onRowClick?: …
See versioning and deprecating inaccessible component APIs.
Step 6 — Test foundations in CI
Permalink to "Step 6 — Test foundations in CI"Token contrast tests, target-size and text-spacing tests per density, contract-generated keyboard tests and ARIA snapshots per component state.
Keyboard interaction contract
Permalink to "Keyboard interaction contract"The design system’s contracts are the product’s keyboard contracts. For grids, the core contract every component should share:
| Context | Keys | Action |
|---|---|---|
| Navigation | Arrows, Home/End, Ctrl+Home/End, Page Up/Down | Move focus |
| Selection | Space, Shift+Space, Shift+arrows, Ctrl+A | Select rows or ranges |
| Editing | Enter or F2, Escape, Tab (in entry mode) | Edit, cancel, move |
| Commands | Shift+F10, Ctrl+C, ? | Menu, copy, help |
Screen reader compatibility matrix
Permalink to "Screen reader compatibility matrix"Foundations are verified with screen readers through component tests rather than per product:
| Foundation | Verified how | Readers |
|---|---|---|
| Name and row header props | ARIA snapshots + manual check | NVDA, JAWS, VoiceOver |
| Message props | Speech log or manual check | NVDA, VoiceOver |
| Focus tokens | Visual tests (not screen reader) | — |
| Density tokens | Target and spacing tests | — |
| Contracts | Generated keyboard tests + manual announcements | NVDA, VoiceOver |
Edge cases & failure modes
Permalink to "Edge cases & failure modes"1. Optional accessibility props
Permalink to "1. Optional accessibility props"Diagnosis: most usages omit them. Fix: required props with codemods.
2. Tokens verified on one surface
Permalink to "2. Tokens verified on one surface"Diagnosis: focus passes on the page, fails on selected rows. Fix: test every surface pair.
3. Density shrinking targets
Permalink to "3. Density shrinking targets"Diagnosis: compact checkboxes at 14 px. Fix: separate target minimums.
4. Contracts in wikis
Permalink to "4. Contracts in wikis"Diagnosis: docs drift from behaviour. Fix: contracts as data with generated tests.
5. Silent breaking changes
Permalink to "5. Silent breaking changes"Diagnosis: required props added in a minor. Fix: warn, codemod, remove in a major.
Designing accessibility props for grid components
Permalink to "Designing accessibility props for grid components"Required name and row header props, typed messages with i18n defaults, safe defaults and narrow escape hatches. See designing accessibility props for grid components.
rowHeader: keyof Row;
Density tokens and target size in data grids
Permalink to "Density tokens and target size in data grids"Visual density separated from hit areas, minimum heights instead of fixed heights, every density verified. See density tokens and target size in data grids.
.cell-control { min-inline-size: var(--target); min-block-size: var(--target); }
Focus ring tokens across themes
Permalink to "Focus ring tokens across themes"Two-tone outline rings verified against every surface, inset in dense grids, preserved in forced colours. See focus ring tokens across themes.
@media (forced-colors: active) { :focus-visible { outline-color: CanvasText; } }
Documenting keyboard contracts for components
Permalink to "Documenting keyboard contracts for components"Contracts as data that render docs and help dialogs and generate tests, with deviations explicit. See documenting keyboard contracts for components.
{ keys: ['Shift+F10'], action: 'Open row menu', focus: 'first menu item' }
Versioning and deprecating inaccessible component APIs
Permalink to "Versioning and deprecating inaccessible component APIs"Warn, provide replacements, migrate with codemods, measure adoption and remove in majors, citing WCAG. See versioning and deprecating inaccessible component APIs.
console.warn('[Grid] onRowClick is deprecated (keyboard users cannot activate rows). Use rowAction.');
Cross-cutting concerns
Permalink to "Cross-cutting concerns"Documentation. Put an “Accessibility” section at the top of every component page: required props, keyboard contract, announcements, known issues. Teams read the top of pages.
Ownership. Each foundation needs an owner: tokens (design), props and contracts (engineering), tests (QA or platform), deprecations (release management).
Feedback loops. Product bugs that trace to foundations should be fixed in the design system first, then rolled out; track how many product bugs each foundation change prevents.
Multi-framework systems. Keep tokens and contracts framework-neutral (JSON) and generate framework-specific outputs from them.
Worked example: a design system accessibility year
Permalink to "Worked example: a design system accessibility year"A design system serving 25 products spent a year on foundations rather than per-product fixes. Quarter one: required label and rowHeader props with codemods. Quarter two: density tokens with target minimums and focus tokens verified on every surface, with token tests in CI. Quarter three: keyboard contracts as data for grid, tree, menu and combobox, generating docs, help dialogs and tests. Quarter four: deprecation of onRowClick, statusColor and the compact boolean. Product-level accessibility bugs related to these areas fell by more than 70%, and new products started at a far higher baseline.
Who is affected, and how
Permalink to "Who is affected, and how"| Group | Effect of strong foundations |
|---|---|
| Users of every product | Consistent, accessible behaviour by default |
| Product teams | Fewer decisions; accessible path is the easy path |
| Design system team | Fixes once, benefits everywhere |
| QA | Tests generated from contracts and tokens |
| Leadership | Measurable reduction in product-level bugs |
Getting started with foundations
Permalink to "Getting started with foundations"Most design systems already have tokens and components; accessibility foundations are an evolution rather than a rebuild. Start by measuring: how many grid usages set a name, which surfaces fail focus contrast, which densities fail target size, which keys components handle without documentation. Those measurements identify the highest-value foundation changes. Then fix in this order — focus tokens (immediate visual benefit everywhere), required name props (largest screen reader benefit), density tokens (pointer users), contracts (long-term consistency) — and use the deprecation process for anything that changes APIs.
Working with product teams
Permalink to "Working with product teams"Foundations only help if products adopt them. Publish short migration guides, run office hours during major upgrades, provide codemods for mechanical changes, and show teams their own numbers (unnamed grids, failing focus surfaces) before and after. Product teams generally welcome changes that remove work from them; the required-prop approach removes the need to remember accessibility details in every screen.
Design system integration
Permalink to "Design system integration"This topic is itself about design system integration; the key practice is to treat accessibility foundations as part of the system’s public API. Version them, document them, test them, and change them through the same release process as any other API. Publish an accessibility page for the system as a whole listing tokens, contracts, required props, deprecations and known issues.
Common mistakes in design system foundations
Permalink to "Common mistakes in design system foundations"- Accessibility as a per-component checklist rather than tokens and contracts shared across components.
- Optional props for essential semantics.
- Tokens tested on a white page only.
- Contracts nobody can test.
- No deprecation path, so inaccessible APIs live forever.
Measuring foundation quality
Permalink to "Measuring foundation quality"Track: percentage of components with required name props, number of token pairs tested per theme, contracts with generated tests, deprecated API usage remaining across repositories, and product bugs traced to foundations per quarter. These numbers show whether the system is making accessibility easier or merely documenting it.
Foundations for charts and dashboards
Permalink to "Foundations for charts and dashboards"The same foundations apply beyond grids. Chart components benefit from required title and summary props, a table slot, palette tokens verified at 3:1 against plot backgrounds in both themes, focus tokens read by chart renderers for data point highlights, and keyboard contracts for point navigation. Dashboards benefit from layout tokens that keep widgets reflowable at 400% and from a shared announcer contract so widgets do not compete for the speech channel.
Testing checklist
Permalink to "Testing checklist"Tokens
Permalink to "Tokens"Components
Permalink to "Components"Contracts and process
Permalink to "Contracts and process"FAQ
Permalink to "FAQ"Where should a design system start?
With required name props and focus tokens. Both are cheap and fix failures in every product.
Are tokens enough for accessible colour?
Tokens make it possible; tests make it true. Test every token pair that can appear together.
Should keyboard contracts follow the ARIA patterns exactly?
As closely as possible; document deviations with reasons.
How do we handle teams that override design system styles?
Make tokens and utilities the only supported customisation path, and review overrides for accessibility impact.
How do we get product teams to adopt new versions?
Codemods, office hours, adoption dashboards and clear accessibility benefits in release notes.
Should the design system publish an ACR?
Component-level conformance notes help products write their ACRs; products must still test as assembled.
Can foundations cover charts?
Yes: chart wrappers with required titles and summaries, palette tokens, focus tokens for data points and contracts for chart keyboard navigation.
How do we prevent regressions in foundations?
Token tests, contract tests and ARIA snapshots in the design system’s CI, run on every pull request.
How do foundations relate to WCAG conformance?
They make conformance achievable at scale; products still need testing as assembled, because layout, content and integration introduce their own issues.
What tooling helps most?
Style Dictionary or similar for tokens, TypeScript for required props, Storybook for contracts and states, and Playwright for tests.
How do we prioritise foundation work?
By how many product failures each change prevents. Focus tokens and required names usually top the list.
Should accessibility foundations be optional for teams with special needs?
Provide escape hatches, but make them explicit and reviewed. Most “special needs” turn out to be missing features in the foundation, which are better added centrally.
Related
Permalink to "Related"- React data grid libraries — wrapping third-party components
- Headless UI primitives for data — building blocks
- Accessibility governance for data products — process around foundations
- Visual regression & theme testing — testing tokens
- Focus indicator contrast auditing — focus in practice