From two systems to one: unifying Figma's parameter architectures

Figma's dynamic features—responsive design, typography, animations, and state machines—all depend on parameters: values set in one place that propagate throughout a project. Component properties and variables are two prominent examples of such parameter systems, but they evolved separately, each solving different user limitations. By 2024, the cost of maintaining parallel architectures became clear: a variable and a component property could bind to the same layer property, producing inconsistent rendering. Separate codebases also made it nearly impossible to extend parametrization to other Figma products without carrying forward technical debt.

The solution was a unified architecture that now powers both systems under the hood, eliminating user-facing inconsistencies, speeding up development, and providing a scalable foundation for parametrization across Figma products.

Why the systems diverged

Component properties, launched in 2022, brought scoped parametrization to Figma: parameters defined for specific layers within a component, usable only there. This gave design system authors a contract for customization while mirroring properties in code—designers and developers could customize components using the same mental model. This capability later enabled products like Figma Sites, Figma Make, and Code Connect.

Variables, launched in 2023, offered global parametrization: parameters defined at the library level, available to any file with access to that library. Before variables, styles (launched in 2018) parametrized bundled values like font families and sizes, but lacked support for granular properties within elements such as typography gradients. Variables filled this gap, enabling sophisticated behaviors like expressions, conditional logic, and context-aware values that brought static designs to life.

Component properties and variables serve different primary use cases, but at their core they are the same: each defines parameters that bind to granular design properties, and when a parameter's resolved value changes, the bound property updates accordingly. Unification therefore focused on two levels: the data model and the runtime.

Unifying the data model

The key difference between the two systems is where the source of truth lives: component properties reside directly on a component or instance layer, while variables live at the library level. Despite this, unification was achieved at the data model level by sharing two critical aspects: the space of parameter value types and the binding of parameters.

One typespace for all parameters

Previously, component properties and variables maintained completely separate type definitions—VariableType.BOOLEAN versus ComponentPropType.BOOLEAN. Adding a new type required implementing it twice, and cross-system bindings were impossible because, for example, there was no such thing as a number component property.

Consolidating these fragmented typespaces into a single source of truth for boolean, string, and number types unlocked interoperability almost immediately. Cross-system bindings became natural and immediate—a direct enabler for the component property to variable binding feature, since type mismatches no longer stood in the way.

One binding mechanism

The guiding principle: the same set of properties should be bindable across parameter systems, and each layer property should be bound to at most one parameter. Under the old model, each parameter system stored bindings its own way, allowing a single layer property to bind to parameters from multiple systems—creating an unclear source of truth. Adding a third parameter system would have meant building a third binding mechanism.

By updating the data model so that all parameter bindings use a single storage mechanism, a given property can be bound to only one parameter at a time, and any future parameter system can reuse the existing binding infrastructure without reinventing it.

Unifying the runtime

The data model defines how bindings and values are stored; the runtime is what powers dynamic behavior. When a layer's fill color is bound to a variable, changing the variable must update the layer's appearance instantly. Under the hood, this involves four steps:

  1. Parameter usage tracking: Determine which layers use the changed variable.
  2. Invalidation: Gather all affected properties across the design when the variable's value changes.
  3. Resolution: Re-resolve affected properties to determine final values.
  4. Updates: Re-render layers with the new resolved values.

Before unification, each parameter system handled these steps differently, preventing a single contract for how parameter systems worked. The unified flow standardizes all systems to follow the same path:

  • Parameter usage tracking now operates at the most granular level, so that for any parameter, the runtime knows exactly which layer properties are bound to it.
  • Invalidation happens at the property level across all parameter systems—not at the layer level—when user actions such as updating a parameter value, binding a parameter to another, or switching variable modes trigger changes.
  • Resolution re-computes each affected property's value. In simple cases this is a forward lookup on the directly bound parameter, but it can also span multiple hops (transitive resolution, such as when a variable alias—where a variable's value references another variable—chains references across levels) or cross parameter system boundaries (as with component property to variable bindings). The unified parameter typespace enabled a single resolution path that handles these complex lookups automatically.
  • Updates replace one property value with another at render time, working identically regardless of which parameter system triggered the change.

This unified architecture eliminated the user-facing inconsistencies of the past and created a coherent foundation for parametrization across all current and future Figma products.

One foundation for the systems ahead

The unified parametrization layer does more than clean up two divergent code paths. It establishes a consistent, reliable backbone for component properties and variables, which in turn gives Figma a stable platform for the features that build on these systems. The upcoming content management system—a prospective third parameter system previewed at this past Config—will sit directly on this foundation, and it will play an increasingly central role in products like Figma Sites and Figma Buzz.

Authoring flows for variables also see a tangible benefit. With stricter, more granular runtime invalidation, the team has cut the total time required to add, delete, and duplicate variable modes, as well as to change variable values.

Thanks to the countless Figmates who contributed to this effort: Stephanie Cheuk, Randall Koutnik, Peter Hayes, Jon Kaplan, Naomi Jung, Isaac Goldberg, Georgia Rust, Jacob Miller, Brian Lam, and many others involved in rearchitecting design systems at Figma.