Every squad was shipping their own buttons, their own spacing, their own blue. The marketing site didn't match the dashboard. The dashboard didn't match the mobile app. Rebuilding trust in the brand meant rebuilding the pixels behind it.
Light & Wonder had grown through acquisition. Each product team — iGaming, Lottery, SciPlay, B2B portals, internal tooling — had inherited its own Figma files, its own colour palette, and its own definition of "button". The brand team had refreshed the wordmark; the product didn't follow.
When I joined, the brief was blunt: build one design system that every squad would actually use. Not a style guide on a Notion page. A living library — tokens, variants, modes, documentation — that would survive a redesign, a rebrand, and a team reshuffle.
The constraint that shaped everything: this system had to be maintained by one designer, adopted by five teams, and survive being handed to a new owner. If it wasn't self-documenting and token-driven, it wouldn't last six months.
Seven shades of "brand blue" across three products. Heading scales drifted between 18px and 22px for the same role. A user moving between tools felt like they'd changed companies.
Components lived in six different Figma files. Engineers copied hex codes from screenshots. When brand updated the palette, nothing downstream updated with it — every team patched manually.
Designers hand-annotated every spec. Developers re-guessed spacing. A button variant took two review cycles and four Slack threads before it shipped correctly.
Three real constraints shaped every structural decision in the system:
One designer, five teams. There was no dedicated design system team — I maintained Floret alongside product work. Governance rules had to be strict enough that squads couldn't introduce rogue tokens without the graph breaking visibly. Complexity that required manual oversight was complexity we couldn't sustain.
No big-bang migration. Existing product Figma files couldn't be broken mid-sprint. Every component had to be a swap-in replacement — not a forced rewrite. Adoption had to be opt-in and incremental so teams could migrate at their own pace without halting product work.
Engineering approved the naming convention before any component was published. Renaming a token after the first dev sync would have broken the entire token map in the codebase. `color.action.primary` was a joint decision, agreed in writing before component work began — not a design unilateral.
I stopped treating Floret as "a component library" and started treating it as a token graph. Components are the surface; tokens are the spine.
If the tokens are right, one rebrand updates the entire product suite in minutes — not quarters. The architecture I landed on is three strict tiers: Primitives (raw values), Semantic (intent), Component (binding). Every component consumes component tokens. Component tokens reference semantic. Semantic references primitives. Change the primitive — the whole tree bends.
No shortcuts. No component ever points directly at a hex code. The moment that abstraction leaks, a rebrand breaks everything downstream.
Raw values — hex codes, px steps, font sizes. Never referenced directly by components.
Role-based — describes intent, not appearance. Swappable across Light & Dark modes.
The binding — each component consumes only component tokens, never reaches past them.
What — Rebuilt every colour, spacing, radius and type token as a Figma Variable with Light/Dark modes.
Why — Styles can't reference each other. Variables can. That's the only way a three-tier token graph survives inside Figma. Change a primitive variable and every semantic and component reference updates automatically.
Problem solved — One variable swap now propagates across 90+ components and every product screen that consumes them. A rebrand or a dark-mode toggle is a single operation, not a two-week reskin.
What — Each component has variants for state (rest, hover, focus, disabled, loading) and intent (primary, secondary, danger, ghost). Size and layout are component properties, not separate components.
Why — Exploding the variant matrix — Button_Primary_Large_Hover, Button_Primary_Small_Rest, etc. — kills maintainability. Every state needs an update if the design changes.
Problem solved — A designer picks one Button, flips three properties in the panel — intent, size, state — instead of hunting through 30 Button_XYZ files.
What — Enforced a strict rule: components reference component tokens only. Component tokens reference semantic. Semantic references primitives. No exceptions.
Why — The moment a component points directly at #2D5BFF, the abstraction leaks. Dark mode fails. A brand colour change misses that component. The graph only holds if every node points to the layer directly above it.
Problem solved — Dark mode, brand palette tweaks, and accessibility contrast fixes all became single-file changes in the variables panel. No hunt for stranded hex codes.
What — Exported the token graph as JSON (Style Dictionary format) so engineering consumed the same source of truth the designers used — not redline annotations.
Why — Re-typing values into a CSS file is where drift begins. Engineers re-interpret rounding and spacing, and the implementation silently diverges from the design.
Problem solved — Spec drift between Figma and production dropped to near-zero. A token rename in Figma showed up in the codebase on the next sync. No annotation layer. No translation loss.
No component was designed until the token graph was agreed and locked. That sequencing — audit → naming → primitives → semantic → component — is what made Floret maintainable.
Catalogued every button, input, card and icon across five product Figma files. Found 14 button variants, 9 input styles, 7 distinct blues.
Drafted the three-tier architecture with product leads. Agreed on naming (color.action.primary) before touching Figma — convention drift kills systems faster than missing components.
Built 180+ primitive variables with Light/Dark modes. Set up semantic layer. Locked naming and a no-shortcuts rule before opening the gate for component work.
Shipped in waves — foundations first (Button, Input, Card), then composites (Data Grid, Dialog), then patterns. Each wave gated on a dev review before publishing.
Every component in Floret is assembled from three building blocks: a Variable that holds the value, a Variant that defines the state (rest, hover, focus, disabled, loading), and a Property that switches intent (primary, secondary, danger, ghost).
The Figma Variables panel (centre) shows Light/Dark modes mapped to semantic tokens. The Properties panel (right) shows how those tokens bind to a specific component. This is how a button stays consistent across 90+ screens — and stays correct after a rebrand.
Every token earns its place — if it's not referenced by a semantic token, it gets cut from the primitives layer. No decorative colour aliases. No floating type sizes that exist in one file only.
The shadow scale (Depth-1 to Depth-6) maps to an elevation system: lowest depth for borders, highest for modals. Components never invent new shadows — they pick from the six.
Spacing tokens land in real UI — the dashboard shows space.inset.md as sidebar padding, space.stack.sm as row gap. Tokens are only useful if they're visibly governing real decisions.
The icon set (200+ glyphs) is drawn against the same 8pt grid. Nothing feels off-grid when dropped into a card or toolbar — because it literally isn't.
From Accordion to Toolbar, every component is documented with its variants, properties, tokens consumed and accessibility notes. Squads pull from one library; brand updates ripple automatically.
Spec annotation disappeared. Engineering pulled tokens from the same JSON the designers edited.
Replaced 14 button variants, 9 inputs and 7 blues with one Button, one Input, one palette.
Dark mode, brand tweaks and contrast fixes all become single-file changes in the variables panel.
Five fragmented Figma libraries collapsed into one published library consumed by every squad.
The early version of Floret was built entirely on Figma Styles — not Variables. In a single-mode build, Styles and Variables look identical in the panel and behave identically in components. The difference only surfaces when you need modes.
In week 3 we added a Dark mode requirement. Styles can't reference each other — so every semantic token had to be manually duplicated in a second Style list for dark. One colour change meant two edits, in two separate places, with no link between them. The lists were guaranteed to diverge within a month.
Why we cut it: The three-tier token graph only works because Figma Variables support nested references — a semantic token can point to a primitive, and a component token can point to a semantic. Styles are flat. The whole architecture collapsed the moment we needed real multi-mode support. We migrated entirely to Variables in week 4 and rebuilt the semantic layer from scratch. It cost a week. It saved the system.
"A design system only survives if engineering owns half of it. The tokens have to be a shared contract — not a design deliverable thrown over the wall."
What worked. Starting with the token graph — not the components — saved months of rework later. Having Light and Dark modes baked into the primitive layer from day one meant dark mode wasn't a "Phase 2"; it shipped with the library.
What I'd change. I would have set up the Style Dictionary export pipeline in parallel with the Figma work, not after. A month of manual sync between design and code could have been avoided. Next system I build, the JSON export is scaffolded on day one — before the first component is published.