Skip to main content

Figma Components and Variants: Rules That Scale

By · · 5 min read

On this page

Every team eventually builds a component library in Figma. Most start with enthusiasm and end with a familiar mess: dozens of nearly identical buttons, variants nobody understands, detached instances everywhere, and designers quietly building their own versions because the library is too confusing to use.

The difference between a library that scales and one that collapses usually isn't skill. It's a handful of clear rules applied consistently. These are the ones I rely on.

Rule 1: Build from the smallest pieces up#

Start with the atoms: icons, text styles, color and spacing variables. Then build simple components — buttons, inputs, checkboxes, badges. Only then build complex components that combine them, like cards, dialogs, and navigation bars.

Building bottom-up means changes propagate correctly. Update the icon component, and every button, input, and menu that uses it updates too.

Rule 2: One component per concept#

A button is one concept. It might have many appearances — primary, secondary, destructive; small, medium, large; default, hover, disabled — but it should be one component set with variants, not a dozen separate components.

The test: if two things share the same purpose and structure, they belong in the same component set. If they serve different purposes, they deserve separate components, even if they look similar.

Rule 3: Use variants for structural differences#

Variants are for differences that change the component's appearance or structure in defined ways:

  • Type or hierarchy — primary, secondary, tertiary.
  • Size — small, medium, large.
  • State — default, hover, pressed, focused, disabled.

Name variant properties clearly and consistently across the library. If buttons use "Size = Small / Medium / Large," inputs shouldn't use "Scale = S / M / L."

Rule 4: Use component properties for content#

Not every difference needs a variant. Figma's component properties handle content changes without multiplying variants:

  • Text properties for labels and helper text.
  • Boolean properties to show or hide elements, like an icon or a badge.
  • Instance swap properties for choosing which icon appears.

A button with an optional leading icon doesn't need "With Icon" and "Without Icon" variants for every combination. A boolean property and an instance swap do the job with a fraction of the variants.

Rule 5: Avoid variant explosion#

Variants multiply. A button with 3 types, 3 sizes, 5 states, and 2 icon options has 90 combinations. That's hard to maintain and slow to load.

To keep things manageable:

  • Use properties instead of variants for content and optional elements.
  • Question whether every state needs to exist in the library, or whether some only matter in prototypes.
  • Split genuinely different components rather than forcing everything into one giant set.

Rule 6: Every component uses auto layout#

Components should resize gracefully when their content changes. A button that doesn't grow with its label, or a card that doesn't expand with its content, will be detached and modified — and detached instances are where libraries go to die.

Set sensible resizing behavior, min and max widths, and test with long and short content before publishing.

Rule 7: Bind styles to variables#

Colors, spacing, radii, and typography inside components should reference variables and styles, never raw values. This keeps components consistent with the rest of the system and makes theming possible. If dark mode or a rebrand arrives, components update automatically.

Rule 8: Design every state, including the boring ones#

Interactive components need their full set of states: default, hover, pressed, focused, disabled, and where relevant, error, loading, and selected. The focus state is the one most often forgotten, and it's essential for keyboard and accessibility users.

Designing states in the library means designers don't have to invent them per screen, and developers get a complete specification.

Rule 9: Name layers and properties for humans#

Component names should be clear and predictable. A slash-based naming structure — like "Button," "Input / Text," "Input / Select" — helps organize assets in the library panel. Inside components, name layers meaningfully: "Label," "Icon Leading," "Helper Text." These names show up in Dev Mode and help developers map design to code.

Rule 10: Document usage, not just appearance#

A component without guidance will be misused. Add short descriptions to components explaining when to use them and when not to. Link to fuller documentation if your team has it. A single sentence like "Use for the main action on a page — no more than one per view" prevents a surprising number of design inconsistencies.

Rule 11: Make detaching unnecessary#

Every detached instance is a signal that the component didn't meet a real need. Instead of policing detachments, treat them as feedback. Look at why people detached — a missing variant, inflexible layout, a content limitation — and improve the component.

Rule 12: Version and communicate changes#

When you publish library updates, write clear release notes: what changed, why, and whether anything breaks. Batch small changes rather than publishing constantly. And for breaking changes, give teams a heads-up and a migration path.

A library is a product, and its users are your fellow designers. Treat them accordingly.

Match the code#

The ultimate goal is alignment between design and code. Component names, variant properties, and states should mirror the coded component library as closely as possible. When a designer says "Button, secondary, small, with leading icon," a developer should know exactly which coded component and props that means.

When Figma and code speak the same language, handoff gets faster, inconsistencies drop, and the design system starts doing what it was meant to do: letting teams build better products with less effort.