The most common way to build a Design System in Figma is to create one Variant for every combination of Component Properties. As a result, a single Component contains every possible case that can be represented by its Property combinations.

The problem begins as more Properties are added or existing Properties gain more Property values. As the number of possible combinations increases, so does the number of Variants that must be maintained.

When the meaning or styling of an existing Property value changes, every Variant using that Property value must be updated. When a new Property or Property value is introduced, new Variants must first be created for every possible combination with the existing Properties before their styles can even be defined. In other words, the amount of work required to maintain and update Variants grows rapidly.

Eventually, this leads to Variant explosion. Components become increasingly complex, and that complexity can also carry over into projects that use the library.

In this note, I'll introduce 4 approaches I have used to reduce the number of Variants while preserving the same number of Component property combinations.

1. Separated components

Split a Component into multiple Components based on a specific Property. Although they represent the same UI element from the user's perspective, Figma treats them as separate Components.

Pros
  • Reduces the number of Variants within each individual Component without requiring major architectural changes.
  • Components can still be built entirely with primitive values, without relying on Styles or Variables.
  • Component-related settings are split across only two controls: "Swap instance" and "Instance Properties".

Cons
  • The total number of Variants remains the same. As a result, the amount of work required to maintain Property values does not decrease.
  • Since they are separate Components in Figma, switching between their Instances may break overrides.
  • If separated Components support different sets of Values for the same Property, switching to another Component may reset the current Property value to its default because the original Value is no longer available.

Notes
  • If Component names contain "/", Figma automatically groups them by path, allowing related Components to appear together.
  • Only the final segment of the path is displayed as the Component name, making it more difficult to identify the original Component represented by an Instance.

2. Two-layer components

Instead of directly modifying a child Instance's Property values to reflect the parent Component's Property values, keep the child Instance's Properties at their default values and override only values that are not controlled by those Properties. I call this approach "Two-layer Components" because the Component is intentionally split into two independent layers, each responsible for a different set of Component Properties.

For example, a lower-level Form Component defines structural properties such as size and layout, while an upper-level Appearance Component defines the colors used to represent different hierarchy levels and interaction states such as hover and disabled.

Pros
  • Significantly reduces the number of Variants, especially those created by combinations of multiple Properties.
  • Components can still be built entirely with primitive values, without relying on Styles or Variables.
  • Component-related Properties are managed entirely within "Instance Properties".

Cons
  • As Component hierarchies become more complex (e.g. a Checkbox Group containing multiple Checkbox Items), preserving existing overrides becomes increasingly difficult.
  • Since the parent Component simply wraps a child Instance inside an empty Frame, every Instance contains an additional layer.

Why can nested Components break overrides?
  • For example, applying an "Error" state to a Checkbox Group requires the Group Component to set the "Error" Property Value on all child Item Components. If a child Item Instance only contains content overrides such as a custom Label, those overrides are preserved.
  • However, if the Item Instance already overrides one of its own Component properties (such as its "Checked" state) and therefore references a different Variant from the one expected by the Group component, switching the Group to the "Error" state may cause the Instance to reference another Variant. In that case, existing overrides may no longer match the newly referenced Variant and may therefore be reset.

3. Components with variables

Define Variants using Variables. However, rather than simply replacing primitive values with Variables, each Variable name itself should represent specific Property values.

For example, "color-action-plain-strong-fill-hover" represents the Property values for "Color", "Hierarchy", and "State". "spacing-comp-md" represents the Property value for "Size".

Pros
  • Moves Property management from the Component to Variables, eliminating the need for separate Variants for those Properties.

Cons
  • Variable naming conventions must represent Property-related information.
  • Property information becomes separated from the Component itself. Components no longer directly know which Property values are represented by Variables.
  • Changing a Property value requires manually replacing every related Variable, increasing the chance of human error.
  • As the number of affected Instances grows, so does the amount of manual work required.

4. Components with variable modes

Define Variants using Variables. However, instead of letting each Variable represent a single design token directly, use Variables with Modes to switch between different design tokens. In other words, use Variable Modes — typically intended for themes such as Light and Dark modes—as if they were Component Properties.

Pros
  • Moves Property management from the Component to Variables, eliminating the need for separate Variants for those Properties.
  • Although Property information is still separated from the Component itself, it can now be accessed through Modes in the Appearance panel, making that Property-like information visible from within the Component.
  • Changing a Property value requires only switching the Mode, allowing all related Variables to update at once.

Cons
  • Variable naming conventions must still represent Property-related information.
  • Additional Variable collections must be created specifically to replace Component properties.
  • During developer handoff, designers and developers must understand that the Variable applied to the design is not necessarily the actual design token to implement. Instead, they need to identify the selected Mode and then determine the actual design token

Tags
Component
Design system
Optimization
Workflow
Published on
July 6, 2026
Works