Skip to main content

Selected work · Design system build

From drift to design system.

How a drifting product UI grew into foundations the team would actually use. The case is sanitised here because it was client work; the artefacts and the thinking are the same. A private walk-through is available on request.

Context

What I walked into.

Multiple teams shipping in parallel into a UI that had drifted for years. No canonical tokens. A component library that existed on paper but that nobody trusted enough to use. The styles in production looked the way they did for reasons documented in someone's head, or buried in a pull request from two years ago.

Nobody had asked for a redesign. They needed something a new hire could open six months later and follow without a call: named tokens, a component library with documented states, and a one-paragraph 'why' for every non-obvious rule.

Recreated diagram Four teams, four local truths.

The audit grouped drift by colour, spacing, and component choice rather than by screen. That made the system problem visible without exposing the product.

Team Colour Spacing Component
Feature A Brand green 12 / 16 / 20 Local button
Feature B Marketing green 8 / 16 / 24 Legacy button
Feature C Product green 16 / 20 / 32 Inline styles
Feature D Grey override 12 / 24 / 40 Forked card

Before

Symptoms, not solutions.

What I built

Tokens, components, docs, workflow.

Four pieces, all reinforcing each other. Removing any one of them brought the old habits back within a sprint.

Tokens
Three layers with naming treated as the public API. Components only see the semantic middle; raw values stay in the basement where nobody trips over them.
Components
A small set, built against semantic tokens. Every one ships with documented states and accessibility behaviour written where someone might actually find it.
Documentation
Short, opinionated docs that live next to the code. Intent and trade-offs first, usage second. Long documentation pages got ignored, so I stopped writing them.
Design-to-code workflow
Figma variables, code tokens, and components are wired so a change in one place updates everything downstream. Design and engineering finally argue about the right things.

Primitive → Semantic → Component

Token architecture.

Three layers and a rule. Components only consume the semantic middle. Raw values stay where they were defined, and nobody writes a hex code in a component file.

Components only read from the semantic layer. Primitives stay invisible.
/* Layer 1: primitive (the only place raw values live) */
:root {
  --ds-color-sage-500: oklch(0.86 0.13 130);
  --ds-space-200: 16px;
  --ds-radius-300: 6px;
}

/* Layer 2: semantic (what components reach for) */
:root {
  --color-accent: var(--ds-color-sage-500);
  --space-control-x: var(--ds-space-200);
  --radius-control: var(--ds-radius-300);
}

/* Layer 3: component (semantic in, never primitive) */
.c-button {
  padding-inline: var(--space-control-x);
  border-radius: var(--radius-control);
  background: var(--color-accent);
}
Sanitised reconstruction The Figma library used the same three-layer contract as code.

This is a recreated variables panel, not a client screenshot. The names are representative of the architecture, with product-specific values removed.

Primitive

  • sage.500
  • space.200
  • radius.300

Semantic

  • accent
  • control.x
  • control.radius

Component

  • button.bg
  • button.padding
  • button.radius

Component anatomy

One button, every decision.

The button is the smallest thing that touches every part of the system. Six token decisions hiding inside one component.

Publish prototype
Background
--color-interactive-bg
Foreground
--color-interactive-fg
Padding
--space-150 / --space-300
Radius
--radius-400
Type
--font-family-ui / --font-size-100
Focus ring
--color-border-focus
Specimen panel The same token vocabulary had to survive component states.

The input is recreated from the public design-system rules: state, copy, spacing, and focus behaviour are the proof, not the client UI.

Default Project title

Neutral surface, no validation copy.

Focus Project title

Ring uses the same focus token as buttons.

Error Project title

Copy carries the error; colour is supporting evidence.

Disabled Project title

Lower emphasis without changing layout.

Lessons

What actually changed the work.

  1. Adoption is the design system.

    A token file nobody uses is a hobby project with extra steps. Most of the actual work was on the boring stuff. Short names. Defaults that matched the common case. Docs that answered the question in the first paragraph instead of the fifth.

  2. Naming is the API.

    The names outlive the values. A team can swap `--color-accent` to a different hex three times and the product stays coherent because everyone reached for the same vocabulary. Rename a token, though, and you will feel it in every diff for a week.

  3. Diagrams beat docs for intent.

    A two-minute drawing of the layers did more for onboarding than the whole usage page. People copy what they can hold in their head, and a paragraph of prose does not stay there.

Private walk-through

Want to see the real artefacts?

The case is sanitised here on purpose. If you want to see the actual Figma library, the tokens running in production, and the docs the team uses every day, I am happy to walk you through it on a call.

Book the walk-through