Skip to content

Publish per-variant figma-SVGs so the Figma file can carry the full state x theme x size x locale matrix #261

Description

@yschimke

Follow-up to #258 / #260. The Figma file is now structured one page per screen,
each major state a bordered section of captioned variant cells — but most cells
can't be filled, because the artifacts branch doesn't publish the renders.

The constraint

scripts/design-artifacts/figma-svg-emit.mjs in compose-ai-tools emits one
figma-SVG per component function, deliberately preferring the light variant
:

Map componentFunction -> { id, svg } for each preview that carried a
compose/figma-svg. Prefer the light variant so a single deterministic
sticker is emitted per component.

So figma/<slug>.svg is always light, compact, default locale. Everything else
on the branch is raster (images/<slug>/…png). Current coverage in the Figma file:

Axis Coverage Cell type
State Full — every state has its own section vector
Theme light vector + dark PNG for the 6 Device states; no dark render at all for cached device, the 3 chat screens, settings mixed
Locale device-cached de/ja/ar, settings-ready de. Nothing else PNG
Size compact (412 dp) only

PNG cells are reference imagery, not a design source — they aren't editable in
Figma, which is the whole point of the design-led direction.

Three workstreams

1. Per-variant figma-SVG export (upstream, compose-ai-tools)

Emit one SVG per preview variant rather than per component function, keyed by
the same ideal__<state>[__theme][__size][__k-v…] scheme catalog-variants.mjs
already uses for PNGs. Needs a delivery-branch layout that doesn't collide —
e.g. figma/<slug>/<variant>.svg — and a matching update to
rewriteRasterHrefs for the hybrid sticker crops.

Blocks everything below: without it, extra breakpoints and locales only produce
more PNGs.

2. Breakpoints (this repo) — PARKED until the app has adaptive layout

Two corrections to the original framing here.

First, the breakpoints field in catalog.spec.json is inert. Nothing reads it —
no consumer in design-parity's catalog-export, none in compose-ai-tools'
generate-design-catalog.mjs. Editing it changes nothing. A component's size comes
from the preview's own @Preview(widthDp = …), normalized through sizeForWidth() in
design-parity packages/core/src/size.ts:

compact < 600dp     medium 600-839dp     expanded >= 840dp

Devices.PIXEL_7 is 411dp, which is why everything lands in compact. So adding size
coverage means authoring wide @Preview functions, the same shape of work as the
locale variants below — not a config edit.

Second, the app has no adaptive layout to render at those widths: no
BoxWithConstraints in app/src/main or meshcore-components/src, no
material3-adaptive or window-size-class dependency in gradle/libs.versions.toml,
and every parity preview pinned to Devices.PIXEL_7. Wide previews today would render
the single-column layout stretched, and publish a Figma "design" for a form factor the
code never adapts to — a reference that either gets ignored or fails forever.

Parked by decision. Revisit when the app gains window-size-class branching, at
which point the previews should use the widths the code actually switches on.

3. Locale previews (this repo)

Locale variants are hand-written @Preview functions — device-cached has
de/ja/ar and settings-ready has de, via the spec's variants array:

"variants": [
  { "props": { "locale": "de" }, "preview": "CachedDeviceBodyGermanPreview" }
]

Authoring en/ar/ja/de for the remaining screens is ~30 new preview functions.
Worth confirming the set of "blessed" locales first — ar earns its place as the
RTL check, ja for CJK line-breaking; de mainly stresses string length.

Why it matters beyond the sticker sheet

Seven design-map.json entries still resolve to committed HTML because they have
no Figma node — DeviceBodyPreview and every *DarkPreview. Dark figma-SVGs
from workstream 1 would close most of that gap and let .design-parity.json move
to design-led.

Related

  • Status-bar mismatch: the seeded renders carry the synthetic OS status bar that
    the HTML references deliberately omit (see "Render path" in
    docs/design-parity.md). That needs settling before the direction flips, and
    may resolve itself via compose-ai-tools#1930.
  • docs/design-parity.md -> "Variant coverage (and why it's uneven)".

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions