Properties, styles, and tokens
You can end up with sixty variants of one button — every combination of size, icon, and state — and a panel no one can navigate, because you modelled with variants what should have been properties.
Choose your track
Read this module through your lens
The combinatorial trap
Variants are so satisfying that beginners use them for everything, and that leads straight into a wall. Model a button’s size (3) times icon-or-not (2) times state (3) as variants and you already have 18; add one more option and it doubles. The properties panel becomes an unnavigable grid, and every new dimension multiplies the work. This is the combinatorial explosion, and it is the classic intermediate failure.
The escape is a distinction. Some choices are mutually exclusive states of one thing — a button is default OR hover OR disabled, never two at once. Those are variants. Other choices are independent options that combine freely — size, whether an icon shows, what the label says. Those should be component properties, not variants. Get this split right and the same button that needed 18 variants needs 3 variants and a handful of properties.
Properties: options without explosion
Component properties let an instance expose adjustable options in the panel without creating new variants. There are a few kinds, and each replaces a whole axis of variants. A boolean property toggles a layer — “show icon?” — instead of doubling your variant count. A text property exposes a label for editing without diving into the layer. An instance-swap property lets you choose which icon or sub-component goes in a slot. An exposed nested property surfaces a child component’s controls on the parent.
The mental model: variants are the states the component can be in; properties are the knobs you turn on any state. Size becomes a property, icon visibility a boolean, the label a text property — and suddenly the component is both more flexible and far simpler, because options multiply additively in the panel instead of multiplicatively in the variant grid.
Styles and tokens: change once, theme everything
The other intermediate leap is getting values out of the components. A button with the colour typed in as a hex value, padding as a magic number, and a font set inline is a button that must be edited by hand to change anything global. Multiply by a real system and a brand tweak or a dark mode becomes days of work.
Styles and variables fix this. A colour style or a colour variable is a named, central value — “brand/primary”, “surface/raised” — that components reference instead of hard-coding. Text styles do the same for type. Variables (design tokens) go further: spacing, radius, and colour become named tokens grouped in collections, and you can swap the whole collection — a light set for a dark set — to re-theme the entire product without touching a single component.
This is also the cleanest bridge to engineering: these tokens are essentially the design tokens the codebase will consume, so a tokenised Figma file is already speaking the build’s language.
Hands-on exercise
Take your button component and refactor it: keep variants only for true states, and convert size and icon-visibility into properties (a size property, a boolean for the icon, an instance-swap for which icon, a text property for the label). Move every colour to a colour variable and the type to a text style. Then build a second variable collection for dark mode and prove you can re-theme the whole thing with one swap. Capture the before/after of the component panel.
Second case · a button with size and icon options
The same lesson, a different object
A button modelled with variants for every combination: small/medium/large x icon/no-icon x default/hover/disabled — 18 variants and climbing.
The variant panel is unusable, adding a 'loading' state doubles everything, and the colours are hard-coded hex so dark mode means editing all 18.
Keep variants only for state (3). Make size a property, icon a boolean + instance-swap. Move colours to variables. Dark mode becomes a one-click collection swap; the panel becomes readable.
Common failures · spot them fast
The failure gallery
Combinatorial explosion — a variant for every option combination
Hard-coded hex colours instead of a colour style/variable
Magic numbers for spacing/radius instead of tokens
No theming path (light/dark requires editing every component)
Properties and variants used for the wrong kind of choice
Each of these is caught by a quality gate — keep the cheatsheet open while you work.
Worked example
See the journey
The pattern
Cheatsheet
Cheatsheet
Recipe & shortcuts
Independent options -> component PROPERTIES: boolean (show icon?), text (label), instance-swap (which icon).
Mutually exclusive states -> VARIANTS (default/hover/disabled).
Colour/type/effects -> STYLES. Reusable values (colour, spacing, radius) -> VARIABLES (tokens).
Theme by swapping a variable collection (light/dark) instead of editing components.
Failure modes
- Combinatorial explosion — a variant for every option combination
- Hard-coded hex colours instead of a colour style/variable
- Magic numbers for spacing/radius instead of tokens
- No theming path (light/dark requires editing every component)
- Properties and variants used for the wrong kind of choice
Key operations
- Add boolean / text / instance-swap properties to a component
- Reserve variants for true states
- Define colour and text styles
- Define variables (tokens) and theme by collection
Quality gates
- Are independent options properties, not variant combinations?
- Do colours and type come from styles/variables, never raw hex?
- Can you re-theme (e.g. dark mode) by swapping a token collection?
- Is the component's panel readable, not a wall of variants?
Workflow steps
- Separate states (variants) from options (properties)
- Convert options to boolean/text/instance-swap properties
- Move colours/type to styles and variables
- Build a second theme by swapping the variable collection
Next module
- sys_governance — keeping the system consistent and alive as a team uses it.
Reflection
Reflection card
Active retrieval — answer from memory before re-reading. Saved to this browser.
You've completed this module when…
- A component that uses properties (boolean/text/instance-swap) for options, variants only for states.
- Colours and type sourced from styles/variables, no raw hex on the component.
- A working theme swap (e.g. light/dark) achieved by changing a variable collection.
Next: sys_governance — keeping the system consistent and alive as a team uses it.
Finish — back to Design Systems & Components →