Carlo Roderos
Work/The Trunkrs Design System

The Trunkrs Design System

Tokens, components, accessibility standards, and the distribution work that made it importable.

01 surface + 6 frames  + 2020–present
index
rolesenior product designerspan2020 → presentsurfaces01frames06

Tokens, components, accessibility standards and the words in the UI, for a company with five products: a merchant platform, a consumer tracking app, an operations app, a customer service panel and a legacy planner. I proposed it shortly after I was hired and built most of it. What has changed twice since is where it lives.

Trunkrs Design System
dimensions3244 × 1592formatPNG · 434 KBsourcedesign system repoframes06statusshipped

The problem

What I found when I arrived was in Adobe XD. I pushed the move to Figma and built most of what followed; the rest came from design collaborators working to the same guidance, with the team's agreement on each piece. The one real upheaval since was the typeface, from Clan Pro to Red Hat around 2023.

As a Figma library it worked, and designers had a source of truth. The trouble was everything downstream of it. A Figma file hands a developer a picture and a set of values to retype, and between the picture and production sits an act of interpretation. Months later you can stand in front of a screen and see exactly where it happened without being able to say why. Production drifts, nobody decided to let it, and the design file goes on being correct in isolation.

Then it started slowing me down too. Once I was building prototypes in real code, drawing the screen first felt like an in-between step on the way to the thing that had to exist.

So the second move, out of Figma and into a repo, made with input from the engineers who would have to read whatever replaced the handoff. AI moved where design work happens: I build prototypes in code now, directing coding agents, and a written spec beside the code is what those agents read. A repo also travels, where a Figma file only opens in Figma.

What it is, and what it deliberately is not

It is documentation-first: written specs, each paired with a preview anyone can open in a browser. 33 components, 6 patterns, 177 icons, and the foundations underneath them. The products are built too differently to share one component library, so the system hands each team the specification and they build to it.

Values are the exception. Anyone copying a colour by hand will eventually copy it wrong, so all 278 values live in one file, and the versions the websites, the apps and Figma read are generated from it. Nobody retypes a number.

Around that sit a short brief for coding agents, the specs for designers and engineers, and the previews as visual proof. The rule that keeps them coherent: code owns values, prose owns meaning.

Decisions worth naming

Specs go out, implementations do not come back. The engineers own the coded components in their own codebase. The system sends them values and specs and never takes values back, because a system that accepts values in both directions has two truths and no way to tell which is current.

A prototype is a question, not an answer. This one I learned by being wrong, below.

Ship the values where they are needed. At first, code could only get the values through its stylesheets. Maps, charts and icons drawn on the fly get their colours from code instead, and had nothing to read, which is plausibly why the maps in the operations app had drifted further from the palette than anything else in it. A version of the values that code can read closed that gap.

Figma kept the jobs it is good at. It still holds the icons and illustrations, and it is the archive and backup for tokens and components. What it stopped being is the thing engineering builds from. It could still be where a new design is tried out before it is real, but nothing has been since the move: the tracking app's redesign went through three rounds of user testing in code.

Onboarding friction is a defect. The system is meant to be extended by anyone on the team without asking me, so a governance file nobody can find their way into is a broken component. Each role gets its own way in: designing a screen, building one, or changing the system each come with an ordered reading list.

Guard the drift, and know what the guards miss. Automated checks hold the previews to the palette, refuse to publish the values when any copy has fallen behind, and fail the build when a colour without enough contrast for text is used as text. That last one exists because the others could not see it. An error red that failed contrast was correct in four documents, correct in the code and generated correctly, and the written rule against it sat two sections away, unread for months. When the rule became a check, its first run found six more.

The last guard is looking. Every spec renders as a preview, and rendering catches what no rule anticipated: a read-only field specified as white, which showed as a bright empty box on any page that wasn't white, and a warning icon so pale it read as a smudge.

The audit, and the part I did not expect

Rather than assert the system was working, I took a copy of the engineers' operations app and counted. The screens carried 52 different colour values written straight into them, 36 of which were not in the palette: fourteen sites of primary text on one near-black, nine of muted labels on one grey, and a cluster of thirteen near-identical violet-greys that collapsed onto two tokens. That is now zero.

Eight of those thirty-six came from us. All eight trace back to one of my own distribution-monitoring prototypes: four from the live file, three from an iteration I had already archived, and one that exists nowhere but a brainstorm scratch file and shipped anyway. The engineers had implemented what design handed them, value for value. The drift I had gone looking for was partly mine. Nobody was careless; a prototype looks exactly like a specification if nobody says which one it is.

So the fix went to the cause. The prototype reads the tokens now instead of keeping its own copy of the values, and archived iterations are marked so a superseded one stops reading as current.

What shipped, and how

The values reached the engineers as a working change to their code rather than a request.

The clearest evidence that the specs travel is two apps someone else designed. I rebuilt every screen that ships in the legacy planner on the design system, without redesigning any of them, and it went to a planner developer as a working app to re-implement from rather than a picture to interpret. Then I did the same for the customer service panel: its shell and ten screens in a week, with a written brief for each. Where staff already read meaning into a colour, as with shipment statuses, the colour stayed. A system that only fits the screens its own author drew has not been shown to work.

The apps send problems back, too. The tracking app set a question and its answers at the same weight, so radio options went from bold to regular across the system. Mocking the merchant platform's spreadsheet importer turned up a document still giving error text a red that fails contrast. The newest component is a file upload field, with an import pattern that reuses the importer's wording. The animated background behind the tracking app and the planner, which each had copied by hand, is now one piece of the system that both use, at a thirtieth of the size.

Honest edges

The component library is bigger than the products need, and we use less than half of it. Early on I designed for a system's worth of completeness rather than for the products in front of me, and every unused spec still has to be maintained, audited and re-versioned.

Green and blue links still fail contrast as text, and that is deliberate. Darkening them enough to pass would drain about a third of their colour, where the red lost almost none, so they keep an underline instead, and a link that has to pass uses violet or indigo.

I do not have an adoption number. What I have: designing against the system is easier than it was, the engineers prefer the repo to the Figma handoff because it is closer to what they work in, and one app's off-palette colours went from 36 to zero.


Frames

Every capture behind the surface above. Each one opens at full size.

Trunkrs Design System

frames06
01

Colour: 11 color-* ramps

02

Typography & marks: 4 type-*, both logo-*

03

Foundations: spacing-scale, radius, strokes, elevation, motion, iconography

04

Components · form & input: buttons, inputs, textarea, select, dropdown, checkbox, radio, switch, slider, chip, calendar

05

Components · feedback, navigation & overlay: the other 17 component-*

06

Patterns & data: modal, drawer, table, scrollbar, dataviz, 3 pattern-*

open original