Back to work

Refract Design System

One design system that becomes a different product for every brand.

Timeline
2026 – Now
Role
Product Designer, with the Refract team
Deliverables
OKLCH color engine, ~130 components, motion system, live Studio, CI token checks
01context

We work with a lot of different clients. I wanted one design system that could become a real product for each of them, instead of the same template with new colors.

Every project started the same way. We would rebuild the palette, the type scale, the component kit, and a Figma library that was out of date within two weeks. When the brand changed, someone lost a week putting the system back together, which was the work the system was supposed to save.

In Refract, a brand is one recipe the whole system reads from:

  • Color two seed hexes expand into the whole palette.
  • Type display and body faces, scale, base size.
  • Shape corner radius, separate for cards and controls.
  • Motion timing and bounce, treated as tokens.
  • Everything else space, elevation, borders, texture, icons, light and dark.

Change one value and the whole system updates with it, live. Nothing gets redrawn or rebuilt by hand.

02insights

Three things I learned building it.

Recoloring by hue is where legibility breaks

Insight 01

"Recoloring by hue is where legibility breaks"

Nudge a hue to rebrand and contrast slips quietly, usually unnoticed until it ships. Low-contrast text is already the most common accessibility failure on the web, and it's getting worse: the 2026 WebAIM Million found 83.9% of the top million home pages had text below WCAG AA, up from 79.1% a year earlier1.

A read-only system goes stale before you notice

Insight 02

"A read-only system goes stale before you notice"

Static docs drift the moment they ship, and most teams have no way to catch it. Only 20% of teams measure documentation coverage at all2, and in an earlier survey 35% couldn't tell what in their own system was old, broken, or still coming3.

People feel color shifts they can't name

Insight 03

"People feel color shifts they can't name"

Ask a client what feels off after a rebrand and they usually can't say. Often it's the math: in HSL the same 10% of lightness lands differently on blue than on purple, so a hue change shifts how heavy or readable the text feels without anyone touching a word4.

03the problem

Building one good component kit is easy. The hard part is a kit that turns into very different products while you edit it live, without falling apart.

Legibility first. A client can pick almost any color, so contrast can't be left to whoever is theming. The system sets text and interface contrast itself, against the real background, on every build, and checks it two ways: WCAG 2.1 and an APCA implementation I wrote from scratch. A color that would be hard to read never ships.

Then stability. A color tool is meant to be poked at, so broken input is normal: a half-typed hex, an old kit, a link shared from an earlier version. Early on, any of those could take the screen down. I fuzzed the color input and found 26 crashes and over 45,000 NaN values leaking into the CSS. Bad input now falls back to a safe neutral, and a broken preview recovers itself on the next slider move.

Then speed. One edit rewrites about 240 CSS variables and pushes them to every component on screen. To hold that while you drag a slider, the theme is cached so it rebuilds once per frame instead of several, and the gallery pans on the GPU to stay at 60fps.

These three took most of the build time.

04outcomes

What shipped, what changed.

  • One recipe drives everything: Color, type, spacing, corners, motion, elevation, texture, icons, and dark mode all derive from the recipe, with no code changes. Seven brands ship built in, and anyone can add their own.
  • The color engine: About 700 lines, no dependencies. Two seed colors generate 79 swatches and 110 named tokens per mode, all contrast-checked. A snapshot test locks the output, so the engine keeps improving without changing a color that already shipped.
  • Around 130 components: Primitives up to full patterns, built only from tokens. CI fails the build on any hardcoded color, which is what keeps live theming reliable.
  • Motion built into the brand: Six springs behind two controls, 46 named motion values, and reduced-motion respected everywhere.
  • The Studio: Live controls on 125 of the 130 components, a pannable wall of screens, and links that restore any state. Copy out the themed globals.css, or a prompt to hand to an AI.
  • A recipe you can take with you: A brand is about fifteen values, so it fits in a link and exports to CSS, Tailwind v4, W3C tokens, and Figma variables. An AI can write one safely, because it never sets text colors and the engine handles contrast.

A note

Still in progress. More to come once it's public.

References

  1. 1.WebAIM Million 2026 (web-wide color-contrast failures)
  2. 2.zeroheight, Design Systems Report 2026 (teams measuring documentation coverage)
  3. 3.Sparkbox, 2022 Design Systems Survey (unclear / stale documentation)
  4. 4.Evil Martians, OKLCH in CSS (perceptual lightness vs HSL)

Next case study

KeeyuAI agent for post-purchase ecommerce operations.