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)".
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.mjsin compose-ai-tools emits onefigma-SVG per component function, deliberately preferring the light variant:
So
figma/<slug>.svgis always light,compact, default locale. Everything elseon the branch is raster (
images/<slug>/…png). Current coverage in the Figma file:device-cachedde/ja/ar,settings-readyde. Nothing elsecompact(412 dp) onlyPNG 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…]schemecatalog-variants.mjsalready uses for PNGs. Needs a delivery-branch layout that doesn't collide —
e.g.
figma/<slug>/<variant>.svg— and a matching update torewriteRasterHrefsfor 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
breakpointsfield incatalog.spec.jsonis 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'ssizecomesfrom the preview's own
@Preview(widthDp = …), normalized throughsizeForWidth()indesign-parity
packages/core/src/size.ts:Devices.PIXEL_7is 411dp, which is why everything lands incompact. So adding sizecoverage means authoring wide
@Previewfunctions, the same shape of work as thelocale variants below — not a config edit.
Second, the app has no adaptive layout to render at those widths: no
BoxWithConstraintsinapp/src/mainormeshcore-components/src, nomaterial3-adaptiveor window-size-class dependency ingradle/libs.versions.toml,and every parity preview pinned to
Devices.PIXEL_7. Wide previews today would renderthe 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
@Previewfunctions —device-cachedhasde/ja/ar and
settings-readyhas de, via the spec'svariantsarray: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.jsonentries still resolve to committed HTML because they haveno Figma node —
DeviceBodyPreviewand every*DarkPreview. Dark figma-SVGsfrom workstream 1 would close most of that gap and let
.design-parity.jsonmoveto
design-led.Related
the HTML references deliberately omit (see "Render path" in
docs/design-parity.md). That needs settling before the direction flips, andmay resolve itself via compose-ai-tools#1930.
docs/design-parity.md-> "Variant coverage (and why it's uneven)".