Skip to content

Adopt platform-keyed conventions across schema, engine, CLI and plugin #372

Description

@nathanacurtis

Problem

Conventions describe one library — the Figma file — and nothing else. A code generator reading a spec has no way to know which of a design system's own components means "text", "glyph", or "container", so it emits host elements: a <span> where the design system requires DsText. Compositions are built almost entirely out of these primitives, so the gap is most of what a composition is.

The same shape has no room for the answer, because it is namespaced figma rather than by platform — and the answer differs per implementation: DsText in React, <ds-text> in Web Components, Text in SwiftUI. Figma is itself one of those implementations, since specs are rendered back onto the canvas.

Two smaller gaps ride along: a spec records every platform a workspace configures rather than the one that produced it, and nothing states the width a component should be shown at when its root resizes to fill a parent it does not have.

Solution

Conventions become platform-keyed, with figma as one implementation among react, web-components and swiftui. Each platform declares which of its components implements each spec primitive, and how the spec's concepts reach that component's props. Each platform is authored as its own file in config/conventions/, named for the platform id.

The spec contract itself does not change: an element stays type: text, and each generator resolves it to its own component at emit time, so one spec serves every implementation.

Acceptance criteria

  • A workspace declares conventions as one file per platform in config/conventions/, the filename carrying the platform id
  • A workspace still holding a single config/conventions.yaml gets an error naming the directory it should become, not a silent fall back to defaults
  • specs generate reads the figma entry and produces specs unchanged from today
  • A generated React artifact emits the declared component for a text element, and routes unmapped styling to the declared stylesProp
  • A container binds to one component, or to a Row/Column/Box trio selected by layout direction
  • A spec's metadata.conventions records only the platform that produced it
  • A component whose root resizes to fill its parent renders at the declared width; fixed and hugging roots are unaffected

Problems

  • Conventions have no platform axis, so there is nowhere to put a spec-to-code binding
  • A generator emits host elements instead of the design system's own components
  • Every platform's conventions share one file, with one owner per section and unrelated review cadences
  • A spec's metadata carries platforms that had no part in producing it
  • A fill-width root has no declared width when shown standalone

Impacted code

  • specspackages/schema (landed), packages/cli (loader, templates, migration, ~24 read sites), site/ docs
  • specs-from-figma — reads the conventions object handed to Component; ~13 source files, ~44 test fixtures
  • figma-from-specsElements, KeyReversal, CodeOnlyProps
  • react-from-specs / webcomponents-from-specs — implement primitive resolution
  • specs-plugin-2 — one translation point in SpecsController

Related Docs

Notes

ADRs 073–079 and 081, on adr/primitive-composition (PR #363).

Order of implementation is schema → specs-from-figma → CLI, since the CLI depends on the engine. Schema is landed; everything downstream is outstanding, including ADR-078's loader, which has no schema-package surface at all.


Implementation details are tracked internally.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

clispecs-cli commandspluginFigma pluginschemaspecs-schema types and JSON schemaspecs-from-figmaTransformer from Figma into specs

Fields

Priority

None yet

Projects

  • Status
    Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions