Illustration of a design token system: semantic tokens reference primitive variables, which hold raw values.
Case Study · Design Systems

Scaling Consistency with Design Tokens

Design Tokens Design Systems Figma
Timeline 2023-2024
My Role Design Systems Lead
Deliverables Token architecture, Figma variable library, naming convention documentation, updated components

At Bitsight, the design team worked from Figma styles, not tokens. The platform already had a light/dark toggle built, so designing a component meant designing it twice, once per theme. I led the adoption of a semantic token system that replaced that manual process, cutting design time per component by 40% and improving product consistency.

160+
160+ primitive variables: raw values, no opinion attached
100+
100+ semantic tokens mapping meaning across the system
2
2 modes shipped: light and dark. Color blind mode proven as a POC
40%
40% less time designing components per mode

A Figma announcement, a rebrand, and a window of opportunity

In mid-2023, Figma announced Variables at their annual Config event. I watched the presentation and felt something click. This wasn't just a new feature. It was an answer to a problem I'd been sitting with for a long time. How do you make visual decisions consistent across a growing product without relying on manual discipline?

The timing couldn't have been better. Bitsight was undergoing a company-wide rebrand. Every product interface would need to reflect new visual standards across multiple platforms. Without a scalable solution, that rebrand risked becoming a slow, error-prone process that would stretch for months.

I saw the rebrand as an opportunity to build the system underneath it properly, so the next rebrand, or the next acquisition, wouldn't cost us the same effort all over again.

I proposed starting with a proof of concept. The Questionnaire feature, which I was already leading as a designer, became the first real test ground. It spanned both the VRM reviewer experience I owned and TMH, which I knew well from my earlier work on ThirdPartyTrust, making it a good test for a token system that needed to hold up across different teams. The POC worked, and I got the green light to bring it to the design system properly.

The challenge of keeping consistency while everything changes

The product suite was growing through acquisitions and new features, but our visual foundation wasn't growing with it. Design worked from Figma styles, and that meant a system that didn't scale. Consistency was the product of a manual process that depended on designers' memory and attention.

The challenge was maintaining consistency while everything around it kept changing.

Products were added and acquired regularly. Legacy interfaces couldn't be replaced overnight. Visual updates were often driven by perception: "make it feel more modern." Changes needed to scale across many surfaces at once. We needed a system that could absorb change, not resist it.

My goal became making updates cascade instead of rippling into chaos, and making consistency the default outcome, not the result of a manual review cycle.

Learning from what already existed

Before designing anything, I audited the existing style system and looked at how other teams had solved similar problems. That let me identify usage patterns, inconsistencies, and opportunities for improvement.

I also studied three design systems as reference points:

Atlassian DS

Their token naming structure, foundation.property.modifier, became the backbone of our semantic layer. It gave us a consistent, readable pattern that any designer or engineer could follow without a reference doc.

Material Design

Their contextual token approach (tokens scoped to specific UI surfaces) influenced how we thought about namespacing contexts like nav or specific scales like riskVector. The class segment was inspired by this system.

Carbon DS (IBM)

Too large in nomenclature for our scale, but useful as a reference for how far a token system can go when the product demands it.

All three were well-designed, but their scale and nomenclature often didn't fit Bitsight's context. When I tried mapping their structures directly onto our products, the cost of adapting them outweighed the benefit, so I kept what was useful from each.

The token architecture

Diagram showing how a semantic token references a primitive variable, which holds the raw value

A semantic token references a primitive. The primitive holds the raw value, never consumed directly by components.

The system is built on two layers. Primitive tokens hold raw values with no opinion. Semantic tokens carry meaning, context, and purpose. Every semantic token follows a naming convention, and that convention became the foundation of the system.

Primitive

Raw values with no interpretation. These tokens name a value but don't assign it any meaning or context. They're the foundation everything else references, never consumed directly by components.

blue.500 grey.100 space.4 radius.md
Semantic

Tokens with purpose and context. Every semantic token carries meaning, context, and purpose. These are the tokens components consume, and the ones designers use to build the interface.

bs.color.text.primary riskVector.color.fill.low nav.color.background

The naming convention:

A design token's name describes how it should be used, and follows the same four-part structure. Any designer or engineer should be able to infer what a token does just by reading its name.

Diagram showing the four named parts of a semantic token: class, foundation, property, and modifier

The four-part naming convention: class · foundation · property · modifier.

1 · Class
The context

Groups tokens that belong to a specific UI context or product concept, whether that's the default design system, a navigation surface, or a scale like risk ratings.

bs riskVector nav
2 · Foundation
The visual attribute type

The type of visual design attribute the token controls, such as color, elevation, or space. It answers what kind of style the token belongs to.

color elevation space radius
3 · Property
The UI element being styled

The UI element the token is applied to, such as a border, background, shadow, or other property. It shows what gets styled.

background text border fill shadow
4 · Modifier optional
The role, state, or emphasis

Additional details about the token's purpose, like its color role, emphasis level, or interaction state. Not every token has a modifier. color.text, our default text color, doesn't need one.

primary subtle low critical hover

Token class:

The class segment is the first part of every semantic token name. It signals which UI context the token belongs to. Not every context needs one, but when a context has its own styling rules, that's when it's worth isolating it in its own class. That prevents accidental overrides and keeps intent clear.

bs: the default

The default namespace for all tokens. Everything that doesn't belong to a specific context lives here, things like typography, spacing, or core UI colors. Example: bs.color.text.primary.

Scales: riskVector, rating, finding

Domain-specific color systems for Bitsight's cybersecurity grades, risk scores, and security findings. Each one gets its own class. Example: riskVector.color.background.gradeA.

nav: the exception to mode switching

The nav bar doesn't switch between light and dark mode. Isolating it in its own class makes that behavior clear and prevents accidental overrides. Example: nav.color.background.logo.

Switching themes across token classes in Figma: the nav bar doesn't change between light and dark, while the rest of the interface does.

Which color do I use for a Grade A? Before I had to check the spec every time. Now I just type riskVector... and the value is right there.
Designer On the rating scale tokens

The class segment was the key decision. Rather than trying to make one universal token set cover everything, we accepted that some contexts, like our cybersecurity rating scales, were different and deserved their own namespace.

Sizing tokens: changing personality without changing components

One of the most satisfying demos I ran for the team was showing what sizing tokens could do. Swap radius values, adjust density, change component height, and the entire product shifts its personality. Compact and sharp vs. spacious and soft. No component was redesigned. Only the tokens changed.

Swapping radius and density tokens shifts the product's visual personality. No components were rebuilt.

Elevation tokens: a system that didn't exist before

Before the token system, elevation and surface had no documentation at all. Elevation was just a judgment call made component by component, with no shared reference and no rules.

Defining elevation tokens made us stop and actually decide what the system should be.

Elevation tokens

The final system uses five tokens. Four surface levels cover the full range of depth in our UI. One blanket token handles the overlay state used by dialogs, drawers, and modals.

Diagram showing the four levels of elevation token

Four surface levels cover the full range of depth in the UI.

Diagram showing the blanket element of an elevation token

The blanket token handles the overlay state: dialogs, drawers, and modals.

Definition of elevation tokens

The complete elevation token set: name, value, and intended usage for each level.

Having these tokens in place means that any new component that introduces depth only has to pick a level.

Consistency that scales

The token system shipped progressively, starting with color tokens, then spacing and typography. At launch it covered 160+ primitive variables and 100+ semantic tokens. The effect was visible immediately: updating a primitive value cascaded automatically to every semantic token that referenced it.

What used to take days (designing two versions of every component for light and dark mode, hunting for the right hex value, manually keeping everything in sync) was reduced to minutes.

Wait, you just changed the mode and everything updated? I had to do this manually every time.
Designer First mode switch in a weekly design review

Before tokens: two components, one purpose

Before the token system, supporting light and dark modes meant designing two separate versions of every component (two sets of colors, two frames). Every design change meant updating both components, and keeping them in sync was a manual, error-prone process.

With tokens, that disappeared. Components referenced semantic tokens, and switching modes meant switching the token set, not rebuilding the component.

two component versions: light + dark, hardcoded vs. one component mode switched via tokens

Before tokens: two separate component versions for light and dark. After: one component, one token switch.

Tokens and accessibility

One of the pain points in our product was the scale color system. Bitsight used red for the undesirable end of a risk or grade scale, and blue for the desirable end. After a rebrand, blue was replaced with green, closer to the red-to-green convention most people expect from a risk scale. That fixed one problem and created another. Red and green are one of the hardest combinations for color blind users to tell apart, which made it an accessibility problem.

As a fix, I proposed an alternative set of tokens for color blind mode. It was never implemented, but it proved switching modes needed no changes to components, only new tokens.

Color blind mode comparison

Color blind mode (proof of concept): same semantic tokens, an alternative primitive set of accessible colors.

This was a direct result of the token architecture. If colors had been hardcoded, adding an accessible mode would have required designing a new set of components for each scale. With tokens, all it took was one set of alternative primitive values.

The users were my teammates

This project reminded me of the first design system I designed at ThirdPartyTrust. The users were my teammates, and me.

I got to see the reactions in real time, in weekly syncs and in Figma comments. There's something different about designing a tool that makes your colleagues' work easier, or seeing their face light up the first time they switch a mode and the whole interface updates in one click.

I used to search for the hex. Now I search for the meaning. I won't second-guess the right value for primary text again.
Designer Assigning a semantic token to a component for the first time

Lessons learned

Studying mature systems helps, but don't force their structure onto your own. Carbon, Material, and Atlassian were a good place to start, but I should have stayed open to changing the naming earlier. It took several iterations to land on a naming convention that worked for our context, and that delayed the project.

Our early conversations with the engineering team were open. They wanted the same consistency and alignment I did, and that willingness told me we were on the right track. I left Bitsight after a company-wide layoff, before the design system could close the gap with engineering's, so I can't include those results in this case study.