Skip to content
CHICKENPIE.Start a project →
Making things

Stop Hardcoding Colors: Build a Real Design System with Figma Variables

A hands-on 9-step tutorial: wire a Primitives, Semantic, and Brand variable system in Figma so your whole file updates from one place, light mode and dark mode included.

Read the paper ↓
Chickenpie mascot Mr. Chicken pointing at a glowing screen showing chaotic color swatches organizing into labeled design system tokens
A PAPER FROM THE DESK
THE DETAILS
At a glance
CategoryMaking things
PublishedAug 31, 2026
Read time5 min
Covered here
  • Design
  • AI Tools
  • Productivity
Client
Chickenpie Tutorial
Year
2026
Services
Figma · Design Systems · Design Tokens

The challenge

Designers hardcode hex values into every layer, so a single color update means hunting through dozens of frames instead of changing one source of truth.

The approach

Build a three-tier Figma Variables system (Primitives, Semantic, Brand) with Light/Dark modes wired into real components, so one value change propagates everywhere.

The result

  • Build a working three-tier variable system from scratch
  • Wire Light/Dark mode switching into real components
  • Stop hand-typing hex codes into individual layers

Here's the end state: change one value in one place, and every button, card, and text label on every screen updates. Light mode, dark mode, both brand themes, all of it, from one click. No hunting through 40 frames for a hex code you swore you already fixed.

By the end of this you'll have a working three-tier variable system (Primitives, Semantic, Brand) wired into actual components, with a working light/dark toggle. It won't be a full design system. That takes weeks and a team argument about naming conventions. But it'll be the real skeleton, and it'll be yours.

A messy flat-vector UI mockup with scattered mismatched hardcoded hex color swatches stuck on buttons and cards

We're doing this in 9 steps. Step 6 is where most tutorials wave their hands and say "now apply your variables" like that's a sentence with meaning. It's not. We'll fix that.

Prerequisites

- Figma (any paid or free tier — variables shipped to everyone in 2024, still there in 2026)

- One file with at least a button, a card, and a text style already drawn. Doesn't need to be pretty. Needs to exist.

- No plugins required. This is native Figma.

The steps

1. Open the Variables panel.

Right sidebar, or `Shift+Ctrl+V` (`Shift+Cmd+V` on Mac). You'll see an empty collection called "Collection 1." Rename it to Primitives. This is your raw material: the actual hex values, nothing else.

2. Build your Primitives collection.

Add color variables named by what they literally are, not what they mean: `blue-500`, `blue-600`, `gray-100`, `gray-900`. Resist the urge to call anything `primary` yet. That's a semantic name, and it doesn't belong here. Primitives don't know what they're for. That's the whole point.

3. Create a second collection called Semantic.

This is where meaning lives. Add variables like `color-action-primary`, `color-text-body`, `color-surface-card`. For each one, don't type a hex code. Click the value field and alias it to a Primitive so `color-action-primary` points to `blue-600`. Now you have a layer of indirection, and indirection is the entire trick.

4. Add Light and Dark modes to the Semantic collection.

Click the mode dropdown at the top of the collection, add a "Dark" mode. Now every Semantic variable has two values: what it points to in Light, what it points to in Dark. `color-surface-card` might alias `gray-100` in Light and `gray-800` in Dark. Same variable, different meaning per mode. This is the part styles could never do.

5. Make a third collection called Brand (optional, but do it once so you understand why it exists).

If you ever ship a second brand skin — a white-label client, a seasonal promo — this collection overrides a handful of Semantic values without touching the base system. Skip actually populating it if you only have one brand today. Just leave the shell there. You'll thank yourself in six months.

6. Apply variables to real layers. Here's the part that's actually mechanical.

Select your button's fill. In the color picker, don't pick a swatch. Click the little variable icon (looks like four dots) in the top-right of the picker. Choose `color-action-primary`. Do the same for the card background (`color-surface-card`) and the body text (`color-text-body`). This is tedious the first time through a real file. It gets fast by the tenth layer because you stop hunting for hex values entirely. You're just picking from a short, meaningful list.

7. Test the mode switch.

Select your frame, open the right panel, and under "Applied variables" or via a Dark-mode variant of the frame, swap the collection mode to Dark. Everything you wired in step 6 should flip instantly. If something didn't change, it's still hardcoded — go back and find it. This is the actual QA step, not a nice-to-have.

8. Name things so a stranger understands them in six months.

Use `category-property-variant` order consistently: `color-text-primary`, `color-text-secondary`, `spacing-card-padding`. Inconsistent naming is the single biggest reason design systems rot — not bad tooling, bad naming discipline.

9. Publish the library.

If this file is meant to be shared, click the library icon and publish. Other files on your team can now subscribe to these variables instead of re-inventing them. This is the step that turns "my file's colors" into "the team's system."

Diagram showing Primitives, Semantic, and Brand variable collections flowing into a tidy UI mockup with a light/dark mode toggle

Pro tip

Don't alias Semantic variables directly to raw hex. Always go through Primitives. The one time you skip it "just this once" is the one time a color needs updating everywhere and you find out half your file bypassed the system.

If you get stuck

Mode switching not doing anything? You applied a hex value somewhere in step 6 instead of the variable — Figma lets you do this silently, no warning. Select the layer, check the fill, and look for a plain color swatch instead of the variable chip. That's your leak. Fix it, retest.

Next up

Once your variables are wired, the next fight is component variants that need their own spacing tokens. That's a longer, meaner tutorial, and it's coming.

Share
FROM IDEA TO SOMETHING REAL

What are you making?

Graphics, websites, and curious experiments. Let’s talk about yours.

Talk to the studio ↗
/feed/figma-variables-design-system-tutorial

Have a project in mind?

Tell us what you are making and what you need. An unfinished idea is welcome too.

Start a project →

Another paper for you.

Mr. Chicken at a desk pointing at a laptop screen showing a colorful AI-generated image, with reference photos stacked nearby

6 AI Art Tool Tips That Stop Your Marketing Images From Screaming "AI"

6 quick tips for using AI art tools like Nano Banana and Gemini 3 to make marketing visuals that don't scream "AI" — prompting, texture, consistency, and a pre-publish check.

Open paper
Mr. Chicken at a cluttered home studio desk, working on an AI image generation interface with an uncanny AI-slop draft on one side and a clean composited image on the other

How to Art-Direct AI Images So They Stop Looking Like AI

Nine steps to art-direct AI image generation like a photographer, not a wishlist — light, texture, junk tokens, and the two spots (hands, signage) that always give it away.

Open paper
Mr. Chicken at a nighttime desk poking a laptop screen showing a bouncy Lottie squeeze-toy animation

I Tried to Build a Clickable Lottie Squeeze Toy. It Took Three Tries to Feel Right.

Watch three failed attempts to build an interactive Lottie squeeze toy — from a dead mousemove hack to a broken freeze-frame click, to the segment-based fix that finally feels tactile.

Open paper
Mr. Chicken at a cluttered design studio desk working on a product composite in Photoshop

How to Composite a Product into Any Background Using Photoshop Generative Fill

Drop a product into any background in 10 steps using Photoshop Generative Fill — with matching light, shadow, and zero obvious AI tells.

Open paper
Mr. Chicken at a studio desk with two monitors — Figma design frames on the left, live Framer website on the right with a glowing Publish button

Your Figma File Is Already a Website. Here's How to Publish It in 8 Steps.

Stop waiting for a developer. Here's an 8-step walkthrough for taking your Figma design into Framer and publishing a live website today — no code required.

Open paper
Mr. Chicken at a designer workstation at night, surrounded by multiple screens showing a grid of AI-generated character portraits — some faces matching, some wildly mismatched

I Tried to Keep My AI Character Consistent Across 10 Scenes. Here's What Actually Broke.

Most tutorials skip the step that makes --cref actually work. Here's what failed first, what failed second, and the gotcha that kills most reference image attempts.

Open paper