Risk and Safety Solutions · Design System
Kiwi Design System
Getting five versions of every button down to one — rebuilding the UI foundations of a safety-software suite, and making sure they stayed rebuilt.
Overview
- The problem
- Our components were not unified: each developer had a spinoff of the original component, it was hard to tell which was the latest one to pull because no one pushed — and the documentation had drifted far enough from production code that people stopped trusting it.
- What I did
- Audited the existing UI, rebuilt it as a documented component library on token foundations, led the migration of our docs from Zeroheight into Storybook — next to the code — and introduced a maturity scale so everyone could tell what was safe to use.
- What shipped
- Color, type, spacing, radius, and elevation tokens; a component library with states and edge cases documented; WCAG 2.1 checks built into rollout; and a governance lifecycle that kept the system alive after launch.
The Problem
Risk and Safety Solutions builds the software that safety teams use to keep people safe on the job — the tools behind lab inspections, chemical inventories, and occupational health programs. Around 120 people, a whole suite of products, and one problem everybody could feel but nobody owned.
Our components were not unified. Each developer had a spinoff of the original component, and it was hard to tell which was the latest one to pull, because no one pushed their changes back. Meanwhile our design documentation lived in Zeroheight and Confluence, the real components lived in production, and the two drifted a little further apart every sprint.
Kiwi was our design system, and I was the main designer on it, working directly with the front-end team. My job was to rebuild the foundations, document the library properly, and move that documentation into Storybook — next to the code — so there would finally be a single source of truth everyone could pull from.
Insights
Before touching a single component I wanted to know where things were breaking down, for our internal teams and for customers. The designer before me had kept guidelines and best practices in Confluence, so part of this was going through that backlog piece by piece — keeping what still held up, cutting what had gone stale as the components changed underneath it.
The other part: in a 120-person company, you can just go ask people. So I did — developers, QA leads, product owners, and the customer-facing teams who heard about our UI secondhand, from the people paying for it.
"There's always inconsistency across screens, across products. When our customers ask or point it out, I don't know what to say at times."
"We are looking to the design team to provide clear guidelines on different states of any component, and to account for edge cases."
"I'm not sure which asset to use at times, so I often feel like I have to wait for a team meeting for me to float up my questions."
"Buttons [don't] look like buttons, pretty flat UI, so people are not clicking on it, especially dropdowns."
Three things kept surfacing
Inconsistency wasn't cosmetic. It started as customers noticing screens that didn't match, and it ended as buttons flat enough that people scrolled right past them without clicking. A styling complaint, left alone long enough, quietly becomes a usability problem, then a support problem, then a trust problem.
Engineers wanted completeness, not prettier specs. What does this component do when it's disabled, when it errors, when the text runs long? Our old docs captured how things looked and went silent on how they behaved — so developers filled the gaps by improvising, which fed the inconsistency loop right back in.
When nobody's sure, everybody waits. A designer sitting on a question until the next team meeting, just to ask which asset was current. An end user asking us to please make the dropdowns match. Multiply that hesitation across every designer, every developer, every sprint — that was the real cost.
The three questions we designed against
- How might we deliver a clear guideline to developers, so we limit misalignment between design and dev?
- How might we create a design system sustainable enough to serve every product — legacy and current?
- How might we organize and publish it so people can actually find and read it?
The Solution
Foundations: tokens everyone could pull from
The system starts with primitives that a designer or an engineer could grab without guessing — and with names that match how engineers already think, because the real turning point in closing the design-to-dev gap wasn't a new component, it was calling things text-base and rounded-md so a developer could read a spec and know exactly what to write.
Kiwi Design System
Design Tokens
A single source of truth for color, type, and space — built to keep enterprise EH&S software consistent and accessible at scale.
Typography — text-xs to text-4xl
Respirator fit evaluation
text-4xl · 2.25 / 2.5remRespirator fit evaluation
text-2xl · 1.5 / 2remRespirator fit evaluation
text-lg · 1.125 / 1.75remRespirator fit evaluation
text-base · 1 / 1.5remRespirator fit evaluation
text-sm · 0.875 / 1.25remSpacing — 8pt rhythm, documented as rules
Radius
rounded-sm · 3px
rounded · 6px
rounded-md · 9px
Elevation — seven steps, shadow-sm to shadow-3xl
shadow-sm
shadow-md
shadow-xl
shadow-3xl
The components
With foundations in place, I audited the existing UI and rebuilt it as a library of reusable, documented components: text fields, dropdowns, checkboxes and radios, toasts, tooltips, modals, status chips, navigation, file upload. Each one designed with its full range of states and edge cases — the exact gap engineers had flagged — so a component behaved predictably wherever it appeared.
We built in Figma first to align on visuals. Then I worked with the front-end team as the tokens and specs carried through into code, checking that what shipped matched what we designed.
Buttons
default · blue-500
hover · blue-600
secondary · gray-300 border
disabled · gray-200
destructive · red-600/500
Alerts
success: green-100 surface / green-700 text · danger: red-100 / red-700 — the exact pairing the Aug 2024 palette update fixed
Form input — focused state
Format: campus prefix + 5-digit ID
focus border blue-500 · ring blue-100 · label gray-700 · helper gray-600
Status chips
One source of truth — and rules to keep it that way
We started with polished guidelines in Zeroheight, then watched them fall out of sync with production. That taught us the requirement: documentation has to live where the work happens, or people stop trusting it. So we pivoted to Storybook, and I worked with the front-end team to make sure the tokens were built to the specs we designed.
The other half of staying trustworthy: knowing what's safe to use. I introduced a component maturity scale — every component moves through Proposed, Candidate, Available, Deployed, Best Practice, and Sunset, with plain criteria for each stage (in production at least three months, accessibility and usability solid, no significant open issues). In Figma, a component's status reads at a glance as simple circle icons. It turned Kiwi from a static library into something that could grow, and retire pieces on purpose, without breaking the products that depended on it.
Accessibility, from the start
We followed WCAG 2.1 while designing components, not after — contrast tuned at the token level, and I worked alongside one of our QAs to run checks on color contrast, screen reader compatibility, focus visibility, and readability before the rollout. The palette evolution above shows what that looks like in practice: specific hex values pushed darker so real pairings pass, with the reasoning written down.
The Outcome
By the time my involvement wrapped, Kiwi was integrated into RSS's active platform — the product suite was merging into one global platform, and Kiwi's components went with it — with adoption ongoing. All eight development teams pull components from Storybook rather than rebuilding their own.
Legacy products were a deliberate non-goal. They were in upkeep mode, so we focused Kiwi on the current platform instead of retrofitting products that weren't moving forward. Scoping legacy out wasn't a compromise we settled for — it's what let a small team ship a system the whole company could actually adopt.
Learnings
A design system is a product, not a deliverable. I thought we'd be done when the components existed. We weren't — without a way to track what was safe to use, the library would have drifted right back into the inconsistency it was meant to fix. The governance work turned out to be as much a part of the system as the components themselves.
Documentation has to live where the work happens. We watched beautiful guidelines rot in Zeroheight before we learned this. One living source of truth next to the code beats polished documentation nobody can rely on — it's not close.
Name things for the people who use them. Tokens named the way engineers already think meant alignment stopped being a meeting and started being automatic. I learned to design for the person consuming the system, not just the end user of the product.