Design Token Panel
How to use the live preview token panel, what it edits, and how Apply persists a tweak back into CSS source.
The styleguide ships one live design-token panel: the preview panel, which edits the @zudo-sg/demo-ui component tokens inside the catalog's preview iframes.
Note
This site used to mount a second, doc-chrome panel behind a Design Tokens icon in the header. It was host-only wiring that create-zudo-sg never scaffolds, so it was removed — and the header icon returned as an engine feature instead of bespoke host code.withZudoSg()'s headerTokenTrigger option (default true) injects a header button that opens the very same preview panel documented below; the header control and the workbenchPreview tokens button are two doors into one panel. The button ships hidden and an inline script reveals it only on the engine's own routes (/,/, /); it stays hidden on a regular docs page and on a host page such as / that isn't an engine route. A scaffolded project now gets a working panel out of the box too — see thecreate-zudo-sg README.
Quick orientation
| Preview panel | |
|---|---|
| Trigger | The header's tokens icon (sliders glyph), shown on the engine's routes; also a Preview tokens button (stacked-frames glyph) in a component detail page's workbench toolbar (/); also a "Preview tokens →" button above the dashboards on / |
| What it edits | The @zudo-sg/demo-ui component tokens inside preview iframes |
| Where applied | Preview iframes only |
| localStorage prefix | sg-preview-tweak |
| Console namespace | window.sgPreview |
| Toggle event | toggle-preview-token-panel |
All three triggers dispatch the same toggle-preview-token-panel event and open the same panel. The header icon is hidden outside the engine's own routes (/, /, /); a regular docs page, and a host page such as / that isn't an engine route, show no header control — the workbench and / buttons remain page-local either way.
Preview panel (Preview tokens)
Click the Preview tokens button (the stacked-frames glyph) in a component detail page's workbench toolbar, or the "Preview tokens →" button above the dashboards on /, to open this panel.
The preview panel edits the @zudo-sg/demo-ui design tokens — --color-*, --spacing-*, --font-*, --radius-*, --shadow-*. Instead of writing to the host :root, every change is sent directly into each registered preview iframe's :root via zudo-doc's theme bridge.
Its Palette tab exposes the raw Tier-1 colors as grouped neutral, accent, and state swatches, followed by one tier for each business line: line-vacuum, line-process, line-laser, line-meeting, and line-beauty. Each line has its own hue, and zdtp 0.6's palette validation requires one family per named tier, so the lines stay split into separate groups with their own OKLCH curves. The semantic Color tab keeps the unchanged --color-* names that point at those palette entries.
Why iframes only? In src/ the @zudo-sg/demo-ui target tokens are aliased onto the doc chrome. Writing them to the host :root would corrupt the documentation site's appearance, so the panel deliberately routes all writes into the iframes and leaves the host untouched.
Late-mounted iframes are handled automatically: the registry replays the currently-active overrides into any iframe that loads after the panel has already applied changes. You will see the same token state regardless of which component page you navigate to.
Note
Changes in this panel affect only the component previews in the iframes — the documentation chrome is left untouched.
Its colors are unkeyed by light/dark scheme identity, by design. The ui-color tab is a generic tab: the @zudo-sg/demo-ui family-named palette and light-dark() tokens do not fit zdtp's ramp-reference Color cluster, so adopting scheme scoping there would require redesigning its color model. Note that settings.colorMode (which detects the doc site's schemes) and zdtp's panelSettings.colorMode (which controls the persisted Color identity) are unrelated despite the shared name.
Retheming engine chrome
The panel edits the component library's tokens, not the catalog's own chrome. The styleguide engine's catalog chrome has its own raw --sg-* roles, including --sg-border, --sg-surface, and --sg-accent; those roles are intentionally not part of any panel's saved state. To retheme that chrome, add an unlayered host override such as:
:root {
--sg-border: oklch(0.72 0.02 65);
}The engine declares its defaults under :where(:root), so this override wins before or after @takazudo/. It is independent of the component library's own wind tokens. If an older host used bare --color-border as the engine-chrome hook, replace it with --sg-border; bare --color-border now belongs to the host's own component-token world.
The host component token world has its own :root custom properties and wind token map. zudo-doc 6's theme.css supplies package defaults without resetting host color values; import it before host token styles, then define deliberate host overrides afterward. This import order affects host component tokens, not the raw --sg-* override hook.
Declared defaults on the tokens page
The / page starts with three static dashboards under Declared defaults. The ui-defaults-light and ui-defaults-dark instances, titled UI tokens — mode-dependent defaults (light) and UI tokens — mode-dependent defaults (dark), use include="mode-dependent" to show the rows whose declared values differ by mode. The ui-defaults-shared instance, titled UI tokens — shared defaults (mode-independent), uses include="mode-independent" and chrome="host" to show every other row once while following the site theme. They are read-only reference views with grouped palette strips, actual-size spacing rulers, and multiline typography specimens.
The dashboards are isolated from the token panel and from saved tweaks. Editing the panel never changes these declared-default views. Use Preview tokens → above the dashboards to open the component-preview panel. The page is a declared-default reference; it does not list or copy live host-cascade values.
For the component's API and the build-safe static-rendering pattern, see the TokenDashboard reference and static token dashboard recipe.
Apply — persist a tweak to CSS source
The panel footer also has an Apply button, next to Export / Reset / Load from JSON. Unlike the other three actions (which are entirely localStorage/JSON round-trips), Apply POSTs the current tweak diff to a dev-only endpoint that rewrites the value directly into the project's CSS source — the change survives a hard reload with localStorage cleared, and shows up as an ordinary git diff.
This works for every tab in the panel — Color, Palette, Spacing, Font, and Size — and only when running under pnpm dev (zfb dev). See the caveat below for what's still out of scope.
Apply routes every panel tab now; a few internal prefixes still 400
The apply endpoint routes eight prefixes — palette, color, spacing, text, font, leading, radius, shadow — covering every tab the preview panel exposes: Color and Palette write into packages/; Spacing, Font, and Size (radius + shadow) write into packages/. Apply sends every currently-tweaked token across every tab in one request. The pinned zdtp (>=0.4.7) groups that complete request by resolved target file, so it computes at most one rewrite per affected target file and returns one result row per affected file. Downgrading below 0.4.7 would reintroduce the historical same-file clobber hazard; this grouping does not make disk writes fully transactional.
The failure window is narrowed, not eliminated: any CSS var whose prefix isn't in the routing map — e.g. --breakpoint-* or --default-transition-* (zudo-wind compiler variables, deliberately left out of every tab) — still fails the whole request with "Unsupported cssVar prefix" (400) if it ever reaches the endpoint. None of the tokens the preview panel currently exposes fall into that category, so hitting this 400 through normal panel use shouldn't happen today — but a future token family added to a tab without a matching routing entry would trip it again.
How it's wired, for anyone extending this: the @takazudo/ engine plugin registers a same-origin zfb dev devMiddleware handler (no separate process, no port, no CORS) at /, backed by @takazudo/'s createApplyHandler. The prefix → file routing map lives in zdtp-panel-routing.json at the repo root, and the endpoint/routing values are injected into the engine's preview panel config (createPreviewTokenPanelConfig) via a virtual:zudo-sg-preview-token-panel module that resolves to undefined outside of zfb dev — a production build never sees the endpoint path or the routing map.
Broader apply routing shipped in Takazudo/zudo-sg#130 — palette, color, spacing, text, font, leading, radius, and shadow are all apply-writable now.
Other panel actions
The footer exposes three further utility actions:
Export — downloads a JSON blob of the current overrides. You can copy it and share it, or archive it as a token snapshot.
Reset — clears all overrides, reverting the iframes to their own stylesheet defaults. It does not touch the host document.
Load from JSON — paste an exported blob into the dialog to restore a saved token set. The dialog shows a "Loaded." status message on success and stays open so you can verify before closing.
Tip
Use Export / Load from JSON to hand off a token snapshot to a teammate or to record a design exploration.