chore: sync tokens from Figma - #727
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Note
Copilot could not run the full agentic suite for this review because it was automatically requested on a bot-authored pull request. Request a review from Copilot under Reviewers to retry with the full agentic suite. Improved support for bot-authored pull requests is coming soon.
Adds new design token collections exported from Figma (brand palette, gradients, heading typography, and syntax highlighting colors) and updates the generated token bundle accordingly.
Changes:
- Expanded generated
figma.tokens.jsonmetadata and added light/darkcolor.syntaxtokens. - Added new Figma export JSON files for
brand,Gradient Colors,heading-typography, andSyntax. - Updated resolved token leaf count to reflect the new collections.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/design-tokens/src/generated/figma.tokens.json | Updates generated tokens/metadata to include new collections and syntax colors. |
| packages/design-tokens/figma-export/syntax.json | Introduces syntax highlighting tokens mapped to brand palette for Dark/Light modes. |
| packages/design-tokens/figma-export/heading-typography.json | Adds heading typography tokens (currently only font-family). |
| packages/design-tokens/figma-export/gradient-colors.json | Adds gradient color tokens for Light/Dark modes. |
| packages/design-tokens/figma-export/brand.json | Adds a brand color palette used by other token collections via references. |
`sync-from-export` inferred each collection's role from its shape: the
Light/Dark collection was the semantic colour surface, and anything else
multi-mode was viewport typography. Once Figma shipped `Syntax` and
`Gradient Colors` — both Light/Dark, neither semantic — both landed in
the viewport bucket keyed only by mode name, and whichever file sorted
last replaced the other outright. `Gradient Colors` resolved, was counted
in `resolvedLeaves`, and then left the pipeline without a trace.
Roles are now declared in `src/collections.ts`, keyed by Figma collection
name: semantic | themed | viewport | primitives | registry-only. An
export the manifest does not name stops the sync, as does a manifest
entry whose collection no longer exists, so adding or renaming a
collection in Figma is a decision someone makes rather than one the
resolver guesses. Within a role, two collections reaching for the same
key throws instead of overwriting. Every collection still feeds the alias
registry regardless of role, so `{brand.purple.500}` resolves even though
`brand` surfaces nothing itself.
`themed` collections now reach consumers: `--zl-syntax-*` and
`--zl-gradient-*` with `[data-theme="light"]` overrides, plus Tailwind
aliases (`text-zl-syntax-key`, `bg-zl-gradient-red-start`). They are kept
out of `css/shadcn.css`, which owns the unprefixed shadcn contract.
The snapshot test cannot catch either failure — it only sees names that
already reached `build.ts` — so the resolver spec covers both.
🦋 Changeset detectedLatest commit: d45bbd9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
`:sync-export` runs before the workflow opens or updates the sync PR, so throwing on an unclassified collection killed the run without ever producing a check to go red. The only trace was a workflow log nobody reads — the same invisibility that let the dropped gradient collection through in the first place. An unclassified export now falls back to `registry-only`, the conservative role that surfaces nothing, and is reported in `$source.unclassifiedCollections`; a manifest entry with no matching export lands in `$source.staleCollectionRoles`. The exports still land as a reviewable PR, and `sync-from-export.spec.ts` fails `full-pr` until someone classifies them. `semantic` still throws when zero or two collections claim it: there is no conservative default for "which collection owns color.*".
Review: this sync silently dropped a whole collectionReviewed the token diff and the two Copilot comments. The exports are fine; the pipeline was not. Two commits added here fix it. What was wrong
Separately, nothing in the original diff reached a consumer: CI was green throughout, and structurally had to be — the snapshot gate runs against the built surface, so a discarded collection cannot turn it red. What changed
Snapshot updated with 12 added keys, reviewed as pure additions — no renames, no removals. Figma-side follow-ups (cannot be fixed here)
Neither affects the pipeline; both are wrong provenance. Still hardcodedThe three gradient sites above are now expressible as tokens but unchanged in this PR — that's a follow-up, since it touches console and login rendering and wants its own visual verification. |
`Gradient Colors` now reaches consumers as `--zl-gradient-*`, so the two places that hand-copied its values can reference them instead. This is not colour-neutral. `--zl-gradient-base-end` and `--zl-gradient-neutral-start` carry different light-mode values (`#fafafa` / `#bfbfcf`) from the dark ones both sites hardcoded, so the console account swatch and the pill sheen now follow the theme rather than staying dark in light mode. That is what the tokens describe; confirm it is what the design intends before merging. `pill.css` uses `color-mix` to apply the 0.6 alpha, since `rgb()` cannot take a hex custom property. That is a new idiom in this repo. Leaves `layout-chrome.css` alone: its hero mark already references `--zl-color-icon-default-purple` / `-pink`, and the gradient collection has no equivalent pair (`lavender-start` and `rose-start` differ from those tokens' light-mode values), so swapping would change colours rather than tokenise them. Depends on #727 for the variables to exist.
Automated design-token sync from the Zitadel Design System, plus the resolver change the new collections turned out to need.
Which Problems Are Solved
Figma ships four new variable collections:
brand,Gradient Colors,heading-typography,Syntax.The export resolver classified collections by shape — the Light/Dark one was the semantic colour surface, anything else multi-mode was viewport typography.
SyntaxandGradient Colorsare both Light/Dark and neither is semantic, so both landed in the viewport bucket keyed only by mode name, where the later-sorting file replaced the earlier one outright.Gradient Colorsresolved, counted towardresolvedLeaves, and reached no output.build.tsnever read that bucket either, so none of the new colours reached a consumer.The snapshot gate cannot catch either case: it runs against the built surface, so a discarded collection leaves it green.
How the Problems Are Solved
packages/design-tokens/src/collections.ts(semantic|themed|viewport|primitives|registry-only) rather than inferred from shape. Every collection still feeds the alias registry, so{brand.purple.500}resolves even thoughbrandsurfaces nothing itself.themedcollections emit as--zl-syntax-*and--zl-gradient-*with[data-theme="light"]overrides and Tailwind aliases. They stay out ofcss/shadcn.css, which owns the unprefixed shadcn contract; that file is unchanged.registry-onlyand is reported in$source.unclassifiedCollections, where the resolver spec fails it. Deliberately not a throw —:sync-exportruns before the workflow opens the PR, so throwing yields no check to go red.Additional Changes
None.
Additional Context
figma-export/**is plugin-generated and hand edits revert on the next push: theSyntaxvariable descriptions name a Tailwind palette the values no longer use, andheading-typographytypes"APK Futural"in four places instead of linkingfont/font-serif. Detail in the resolved review threads..github/scripts/design-tokens-open-sync-pr.shregenerates this body on every sync run, so a later designer push will overwrite it.