Design system: from decision to component
A design system is a shared language between product, design, content and code. It speeds up repeated decisions and makes exceptions visible. It is not a gallery of screenshots or a collection of isolated components.
Four levels
1. Principles
Principles filter decisions: clarity before decoration, visible progress, one primary action per zone, accessibility in the structure and explicit feedback after an action.
2. Tokens
A token names a reusable decision: accent color, surface, text, space, radius, shadow, control height or motion duration.
:root {
--sl-accent: #00d1ff;
--sl-text-primary: #ffffff;
--sl-text-secondary: rgba(255, 255, 255, 0.72);
--sl-space-4: 16px;
--sl-radius: 12px;
--sl-control-height: 44px;
}
A semantic name survives a visual change better than --blue-3. Tokens should
not become an unreadable layer of indirection: each needs a documented intent
and place of use.
3. Primitives
A primitive carries a low-level contract: Button, Input, Badge, Card,
ProgressBar, Alert, Modal or Tabs. It uses the right HTML, exposes
states and accepts only necessary properties.
4. Patterns
A pattern assembles primitives for a recurring problem: sign-in form, filtered list, review session, error summary or resume flow. It documents the product decision and must not hide different rules behind one name.
Specify a component
For every component, write a short sheet:
| Question | Example for ProgressBar |
|---|---|
| What problem? | Show progress and remaining work. |
| What role? | Progress with exposed value and maximum. |
| Which variants? | Determinate or indeterminate, according to the contract. |
| Which states? | Idle, updating, complete, error if the product needs it. |
| What content? | “Card 3 of 10”, not a context-free bar. |
| Which constraints? | Readable at zoom, keyboard and screen reader. |
| How to test? | Zero, maximum, dynamic change and assistive technology. |
A variant should exist only for a real intent, priority level or observable
state. Button color="purple" describes appearance; variant="primary"
describes responsibility.
States are part of the contract
Ask:
- how does idle look?
- how are focus and keyboard described?
- what happens during waiting?
- what change confirms success?
- how does an error explain recovery?
- what appears when there are no results?
- why is the action disabled, and what can be done instead?
The component can provide mechanics and style; the page owns context-specific copy. A generic alert must not replace an error that names the field and fix.
Accessibility in the contract
Design accessibility with the primitive: native button before clickable div,
visible label before placeholder, aria-describedby for help and error,
readable focus, aria-live only for changes worth announcing, touch sizing,
responsive reflow and reduced motion.
A page should not have to repair a shared component with five ARIA attributes and a different keyboard handler. If it does, the component contract is incomplete.
Documentation and governance
Useful documentation shows when to use a component, when not to use it, a minimal example, an error example, allowed properties, keyboard and responsive states, content and accessibility decisions, owner, version and change path.
Add a primitive only when the problem is frequent and stable enough for a shared contract. Otherwise, a local composition may be more honest.
Evolve without breaking
- Add a variant only with a real use case and a test.
- Prefer a documented migration to a silent change of meaning.
- Mark a primitive deprecated and name its replacement.
- Check consumers before renaming a token.
- Measure usage or build errors after a major change.
- Keep English rules and copy aligned with French.
Workshop: specify a review card
Write the component sheet before its CSS: role and goal, question and answer, progress, reveal and answer actions, in-progress/completed/error/empty states, control relationships, keyboard/mobile/long-copy behaviour and evidence that the card is complete.
One possible answer
The card is an <article> named by its heading. The question is a heading,
progress is readable text, the answer is connected to the button with
aria-controls and visibility is exposed with aria-expanded. “In progress”,
“completed” and “error” include text. Actions stay in flow, work by keyboard
and stack on mobile. The card is complete when a correct answer and progress
evidence are saved.
System checklist
- Every token has a known intent and usage.
- Every component has a native role, name and documented states.
- Variants correspond to decisions, not free colors.
- Errors, empty states and loading are represented.
- Focus, keyboard, zoom, responsive layout and motion are tested.
- Examples include long content and a translation.
- Contribution and retirement paths are clear.
Reliable sources
- GOV.UK Design System — principles, components and contribution
- Material Design — foundations
- W3C WAI — ARIA Authoring Practices Guide
- US Web Design System — design tokens
Continue with CSS for an interface, then test the system in the interactive UI/UX path.