All work

Case 06of 08

Tessellate Twelve components, not sixty

Four products, twenty-six engineers, three designers and four separate implementations of a button. A change to the date picker took four weeks to land everywhere. The brief asked for a complete design system. We argued for an incomplete one.

Design systemDesign systemPartnerEngagement · 5 months2023
ClientTessellate
4 products, 26 engineers
EngagementPartner · 2 days a week
Duration5 months
then handed over
StackReact, TypeScript,
CSS variables, Storybook
OutcomeDate picker: 4 weeks → 2 days

The library at v2.4 — coverage tracked as the primary metricFig. 01

01 — Chapter

The problem

Tessellate had grown by acquisition and it showed in the interface. Four products, four button components, nineteen distinct greys and no shared tokens between any of them.

The cost was legible in one number the engineering director already tracked: a change to the shared date picker — a regulatory requirement, not a preference — took four weeks to land across four codebases, because it was four separate pieces of work coordinated in a spreadsheet.

  • 4 button implementations, 19 greys, 0 shared tokens
  • Date picker change: 4 weeks across four products
  • Two previous system attempts, both abandoned at around 60% built
  • Three designers maintaining three Figma libraries that disagreed
  • Accessibility defects fixed per product, repeatedly

Before and after

One button, four ways
four products · four buttons
Save Save save Save
19 greys · 0 tokens
Before · four implementations of one button
@tessellate/ui
Save Cancel
v2.4
One source
After · one component, six grey tokens
4 weeks → 2 days

To change the date picker across four products. The same regulatory change, measured the next time it happened.

02 — Chapter

Adoption over completeness

Both previous attempts had failed the same way: build the complete system in isolation, launch it, discover nobody migrates because migration is unpaid work for squads with their own roadmaps.

So we inverted the metric. Not how much of the system is built but how much of the product uses it. We shipped twelve components that covered roughly 70% of real screens, then stopped building and spent six weeks on migration instead — a codemod, a Slack channel and pairing sessions.

  • 12 components chosen by auditing 340 real screens, not by category
  • Coverage tracked weekly and shown to leadership instead of component count
  • Codemod migrated 1,180 call sites; humans handled the 90 it could not
  • A budgeted day per sprint per squad, agreed with the engineering director
  • No component added until the previous one was above 60% adopted

How a component lands

Built, migrated, then the next one
1AuditCount real usage across 340 screens. The twelve most-used patterns, not the twelve most interesting to build.Evidence
2BuildOne component, every state, accessibility included. Shipped behind a version, never a branch.~1 week
3MigrateCodemod across call sites, pairing for what it cannot handle. This is the part previous attempts skipped.~1 week
4StopNo new component until this one is past 60% adoption. Coverage is the metric, not inventory.
Component coverage by productShare of screens using the shared library Month 1Month 5
88%Atlas
79%Signal
64%Quarry
31%Console
71%All four

Coverage is the proportion of rendered screens whose interactive elements come from the shared library, measured by a build-time check rather than self-reported. Console is the oldest product and adopted tokens but not components; it is included here rather than excluded, which is why the total is 71% and not higher.

03 — Chapter

Tokens as the contract

Nineteen greys became six tokens. That sounds like tidying; it is actually the load-bearing decision, because a token is a contract a product can honour without adopting a component.

Console — the oldest and least migratable product — adopted the tokens in a fortnight and the components slowly over a year. It still looks consistent with the others today, and that would not have been possible if consistency had required adopting React components it cannot use.

  • 19 greys → 6 semantic tokens, applied as CSS variables
  • Tokens adoptable independently of components, which is why Console could
  • Figma variables generated from the same source, so the libraries cannot drift
  • Contrast pairs encoded in the tokens rather than checked per screen
  • One accessibility fix now lands in four products in one release

Adoption, tracked

Products against components, month five
ProductButtonFieldSelectDateTableModalToastNav
Atlas
Signal
Quarry
Console
Adopted Partial In flight Not yet

Results

Each with its method
12Components shippedChosen by auditing 340 real screens
71%Coverage across four productsBuild-time measurement, not self-reported
19 → 6Greys reduced to tokensAdoptable without adopting components
1,180Call sites migrated by codemodHumans handled the remaining 90
Two attempts before this one died at sixty percent built and zero percent used. Counting adoption instead of components is the whole reason this one survived.
Sofia RenardEngineering director, Tessellate

LogWeek by week

The build log

Five months at two days a week, alongside Tessellate’s own designers and engineers.

Month 1

Audit. 340 screens catalogued by component usage, nineteen greys mapped, the date-picker cost quantified with the engineering director.

Month 1

Tokens first, components second. Six semantic greys shipped as CSS variables and adopted by two products before a single component existed.

Month 2

Button, field, select. Each one built, then migrated, before the next was started. Slack channel opened and answered within the hour, deliberately.

Month 3

Date picker and table — the two that hurt. Codemod written here, and it paid for itself on the first run.

Month 4

Modal, toast, nav. Coverage passed 50% and leadership stopped asking when the system would be finished, which was the real milestone.

Month 5

Handover to two of their own engineers, who had been pairing on it since month two. Contribution guide written by them, not us.

Since

Tessellate have added nine components without our involvement. We have not been called about it, which is the correct outcome.

What shipped

Six deliverables
0112 componentsButton, field, select, date, table, modal, toast, nav and four others, every state.
02Token setSix semantic greys plus spacing and radius, as CSS variables and Figma variables from one source.
03CodemodMigrated 1,180 call sites across four codebases, re-runnable for future versions.
04Coverage checkBuild-time measurement of adoption, reported weekly without anyone compiling it.
05StorybookEvery state and every accessibility note, generated from the code rather than maintained.
06HandoverTwo of their engineers trained by pairing, contribution guide written in their words.
The part a portfolio leaves out

What we would do differently

We built a documentation site in month two and almost nobody read it. The Slack channel and the codemod did the work the docs were supposed to do — adoption moved when migration became cheap, not when it became well explained. We would now write the codemod before the documentation, and treat a fast answer in a channel as a deliverable rather than a courtesy. The docs eventually mattered, but only after adoption, as a reference rather than as persuasion.

Who did it

Credits
max

System architecture, tokens, eight of the twelve components, codemod, coverage tooling. Two days a week for five months.

Tessellate design

Three designers who built four components and owned the Figma library from month three.

Tessellate engineering

Two engineers paired from month two and took the system over at the end; twenty-six more who did the migrating.

Two build slots openNext start: March

Tell us what you’re building and we’ll scope it

Two working daysA reply from the person who would do the work
One paid weekDiscovery, written scope, fixed price
Yours either wayThe scope document, whether or not you continue
Start a projectStart a project