Skip to content

Across Component Prop Resolution Given Spec Prop Reshaping #369

Description

@nathanacurtis

Problem

A component's spec configures nested instances of other components, but generate has no way to consult those components. Anything that depends on the target's resolved props therefore cannot be applied, and the spec records a shape the target's own API contradicts.

Two places already need it:

  • Visibility pairing. A content prop paired with a visibility boolean is folded into one nullable prop, and the boolean is removed from the target's props. A nested instance still emits both — a bound value beside a false flag — so a hidden slot reads as filled, and the configuration names a prop the target does not have. Instance examples were fixed (DirectedEdges/specs-from-figma#159) because a component's own pairings are in hand; nested instances were not.
  • Slot constraints. Constraints are promoted onto the referenced component's slot prop. When that component is not in the fetched data, the constraint is dropped with a warning.

Both are the same missing capability, so a third case is likely.

Solution

Generate can resolve the parts of another component's API that a configuration depends on, and consolidate against them — without re-processing the target.

A nested instance of a component whose slot is hidden records the slot as unset:

# now
propConfigurations:
  headerVisible: false
  header:
    $slotContent: "#/components/expandoLink/slotContentExamples/checkboxGroupHeader"

# wanted
propConfigurations:
  header: null

When a target cannot be resolved — outside the run, another file, detached — the configuration is left as authored and the reason is reported. It is never guessed.

Acceptance criteria

  • A nested instance of a component with a paired visibility boolean records the content prop alone; the boolean does not appear
  • A hidden slot on a nested instance records the content prop as null
  • An unresolvable target leaves the configuration unchanged and reports why
  • Slot-constraint promotion uses the same resolution path
  • Output is deterministic and independent of the order components are processed

Problems

  • Resolution order — a host may be processed before its targets
  • Targets outside the run, in another file, or excluded from the manifest
  • Cycles, where two components instance each other
  • Cost — the need is a small slice of the target's API, not its whole spec
  • Silence — an unresolved target currently produces the wrong shape with no signal

Impacted code

  • packages/specs-from-figma/src/Component/PropConfigurations/ — where nested configurations are built
  • packages/specs-from-figma/src/Component/Props/PropPairings.ts — establishes the pairing and removes the boolean from props
  • packages/specs-from-figma/src/Component/Props/SlotConstraints.ts — the existing cross-component read and its drop warning
  • packages/specs-from-figma/src/Runtime/Context/interfaces.ts — no shared registry exists today

Notes

Three resolution shapes were discussed, none chosen:

  1. A registry each component publishes as it finishes, read by later components — cheap, but needs a dependency order over instance references
  2. On-demand resolution of a target — order-independent, but recursive with cycles to guard
  3. A pass after generation, once every spec in the run exists — sidesteps ordering entirely, at the cost of a second pass

Depends on the null prop configuration value (ADR-080, #368).

Related: DirectedEdges/specs-from-figma#159 fixes the instance-example half and states this as out of scope.


Implementation details are tracked internally.

Metadata

Metadata

Assignees

Type

Projects

Status
Backlog

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions