Skip to content

CONCEPT Cited by 1 source

Transitive parameter resolution

Transitive parameter resolution is the process of resolving a bound layer property's value by walking a chain of parameter references, potentially crossing parameter-system boundaries, until a concrete literal value is reached.

The chain

Figma's 2026 retrospective (Source: sources/2026-04-21-figma-parameter-architecture-unification) uses the canonical example:

button-primary-bg  (layer property)
    ↓ bound to
button-primary-bg-var  (variable)
    ↓ aliased to
brand-primary  (variable)
    ↓ aliased to
blue-500  (variable, literal color value)

To render button-primary-bg, the runtime walks this chain and returns blue-500's concrete color. A variable alias is a parameter whose value is itself another parameter — the reason chains exist at all.

Why chains cross parameter-system boundaries

Pre-unification, cross-system resolution was structurally impossible — a component property couldn't bind to a variable because their typespaces were disjoint (patterns/unified-typespace-consolidation). Post-unification, a chain can look like:

layer.fill  (property)
    ↓ bound to
button.fillColor  (component property, scoped)
    ↓ bound to
brand-primary  (variable, global)
    ↓ aliased to
blue-500  (variable, literal)

The chain crosses from the scoped parameter system (component properties) into the global one (variables). With a unified typespace the walk is typechecked end-to-end — color is color everywhere. With separate typespaces the cross-boundary edge would be untypeable.

Why "transitive" is the right framing

The naïve mental model is "look up the parameter's value and use it." That works for direct bindings and for parameters whose values are literals. It breaks the moment any parameter's value is itself another parameter. The resolution primitive is therefore not "lookup" but "walk-until-literal" — graph traversal over the parameter reference graph.

This is the same shape as:

  • CSS variable resolutionvar(--brand-primary) where --brand-primary: var(--blue-500);.
  • Symlink resolution — follow until a non-symlink inode.
  • Spreadsheet formula resolution — cell references that themselves contain references.

Correctness concerns

The post doesn't discuss them explicitly, but the reader should note:

  • Cycle detection. Nothing in the naïve "walk until literal" algorithm handles A → B → A. Production implementations must either prevent cycles at binding time or detect them during walk.
  • Change propagation invariance. If blue-500 changes, every property transitively bound to it needs invalidation — including properties bound to brand-primary or button-primary-bg-var or a component property that aliases up into the chain. The parameter-usage tracking index must capture the full reverse transitive closure, not just direct binds.
  • Mode resolution. Variables can have mode-dependent values (light/dark). Resolution must thread the resolving layer's active mode through the chain.

Figma's implementation framing

The retrospective says Figma built "a single path to perform resolution across all parameter systems, which provided automatic handling for more complex lookup patterns like these" — i.e. the resolution primitive doesn't branch on parameter- system identity, it branches on reference-vs-literal at each hop. Unifying the typespace is what let this single path exist.

Seen in

Last updated · 200 distilled / 1,178 read