Figma Variables are a token graph, not a list
April 13, 2026
Figma Variables look like a flat list. Open the panel, and you see names and values, one after another, organized into folders. What you do not see is the graph underneath — which Variables reference which, which collections alias into others, and whether the tier structure you intended is actually there. Most teams discover the answer to that last question when they try to add dark mode.
Two things that look identical in the panel
Figma Variables support two fundamentally different things that the UI renders the same way: raw values and aliases. A raw value is a primitive. An alias is a pointer to another Variable. Both look like an entry in the list. The tool does not impose structure. If you do not bring structure through naming conventions and collection boundaries, you will not get it.
This is not a flaw in Figma. It is a design choice that puts the modeling responsibility on the system designer. You decide what the tiers are. The tool will faithfully hold whatever you give it, whether that is a well-architected three-tier graph or a flat collection of 200 Variables with no discernible structure.
Collections as tier boundaries
The most workable pattern maps collections to token tiers. Three collections, three distinct jobs.
Primitives alias into Decisions, which carry modes. Surface tokens reference Decisions and stay mode-agnostic.
Primitives holds raw values — your color palette, spacing scale, type sizes. Internal only, single mode. A purple-600 swatch does not have a light value and a dark value. It is a fixed point in the scale.
Decisions holds semantic aliases, one per design decision: color/action/primary, color/status/negative, color/surface/default. This is where modes live. Light and dark are decisions about which primitive to use in context — they are not properties of the primitive itself. Putting modes on primitives forces every raw color swatch to carry a light value and a dark value, which defeats the purpose of having a base layer.
Surface holds component-level tokens that reference Decisions. button/background aliases color/action/primary. Consumer designers and engineers reference this layer. When the Decisions layer switches mode, Surface tokens update automatically without anyone touching them.
Where the structure degrades
Figma does not enforce that collections alias in one direction only. Nothing prevents a Surface token from aliasing straight to a Primitive, skipping Decisions entirely. In a system with multiple contributors under deadline pressure, this happens constantly. It is invisible in the panel and invisible in the design until a rebrand changes every Decisions token and three Surface tokens still point at the old palette value.
The defense is process, not tooling. A review checklist that asks "does this alias reference a Decision token?" catches bypasses before they compound. Once tokens are in code, reframe lint flags hardcoded raw values that should reference a token — catching the same class of problem on the engineering side. Neither is a complete solution. Both together significantly reduce the blast radius of a rebrand.
Modes belong at the Decisions tier, not the Primitives tier
This is the most common structural mistake in Figma Variable setups. Modes are scoped to a collection, so if you put all your tokens in one collection and define light and dark as modes, every Variable in that collection gets both modes — including primitives that should not have them.
Separating Primitives and Decisions into different collections means only Decisions carries light and dark modes. Primitives and Surface are single-mode. This maps cleanly to how token resolution actually works: a primitive is a fixed value, a semantic token resolves to different primitives depending on the active mode. Keeping those concerns in separate collections makes the model legible to anyone who opens the file later — not just to whoever set it up.
Figma Variables can model a three-tier token graph with full mode support. The tool does not enforce the structure. In a system shared across a design org, unenforced structure degrades. The difference between a system that survives a rebrand cleanly and one that requires two weeks of triage is usually not how many tokens were defined. It is whether the aliasing respected the tier boundaries that were supposed to exist.