TokenDashboard
Public Preact props, stylesheet entry, defaults semantics, and preview limits for the static token dashboard.
TokenDashboard is a Preact component exported from @takazudo/. It accepts tab data and renders a read-only inventory without browser globals, panel setup, storage access, or hydration requirements.
Availability
The static dashboard subpaths are available from npm v0.6.1. The separatedashboard/client API described below is unreleased and is not in this documentation site's pinned 0.8.6 package. See the static dashboard recipe for build-safe data sharing, stylesheet inclusion, and the live workspace demo.
Exports and props
The named runtime export is TokenDashboard. Public types are available from the same subpath:
import type {
TokenDashboardProps,
DashboardMode,
DashboardInclude,
DashboardChrome,
DashboardPreviewKind,
TabConfig,
TierConfig,
TierItem,
} from '@takazudo/zdtp/dashboard';| Prop | Type / default | Meaning |
|---|---|---|
tabs | readonly TabConfig[], required | Shared manifest data, in display order. An empty array renders an empty inventory. |
mode | 'light' | 'dark' | 'host', default 'light' | Selects declared per-mode defaults and the local preview color scheme. host emits light-dark() values and lets the dependent region inherit the page scheme. |
include | 'all' | 'mode-dependent' | 'mode-independent', default 'all' | Filters visible rows after mode dependence has propagated through references. The complete declaration graph stays available inside the instance. |
chrome | 'light' | 'dark' | 'host', default 'light' | Selects shell, background, and label appearance independently of mode. |
title | string, default 'Token dashboard' | Visible heading and accessible region name. |
id | Optional string | Root element ID; caller owns uniqueness. Omitted IDs are not generated. |
previewText | Optional string; default English/Japanese prose | Static typography passage; explicit empty strings are preserved. |
previewOverrides | Readonly<Record<string, DashboardPreviewKind>> | Per-CSS-variable sample choice. Overrides the tier's preview metadata. |
Load @takazudo/ once through the host's static CSS pipeline. Dashboard JavaScript has no stylesheet side-effect import. This CSS is separate from @takazudo/; the panel stylesheet is unnecessary for a dashboard-only page. Preact is required; no React adapter or HTML-export function/CLI is provided.
Optional imperative client (unreleased)
@takazudo/ exports synchronous mountTokenDashboard(host, props) plus TokenDashboardProps and TokenDashboardHandle types. The handle has an idempotent dispose() method. Use a dedicated empty element from the host's ref; the host keeps ownership of the element and attributes. An initial mount rejects unrelated children. Mounting again through this API replaces the earlier dashboard, and an old disposer cannot clear its replacement. Different hosts are independent.
import '@takazudo/zdtp/dashboard/styles.css';
import { mountTokenDashboard, type TokenDashboardProps } from '@takazudo/zdtp/dashboard/client';
import { tokenTabs } from './token-tabs';
export function setupDashboard(host: HTMLElement) {
// host is an empty element supplied by the host framework's ref.
const props: TokenDashboardProps = { tabs: tokenTabs, mode: 'host', chrome: 'host' };
const dashboard = mountTokenDashboard(host, props);
return () => dashboard.dispose(); // Call on host teardown.
}For a lazy import, the host must ignore completion after its ref is disposed:
export function setupLazyDashboard(host: HTMLElement, props: TokenDashboardProps) {
let cancelled = false;
let dashboard: import('@takazudo/zdtp/dashboard/client').TokenDashboardHandle | undefined;
void import('@takazudo/zdtp/dashboard/client').then(({ mountTokenDashboard }) => {
if (!cancelled) dashboard = mountTokenDashboard(host, props);
});
return () => { cancelled = true; dashboard?.dispose(); };
}The static Preact entry remains suitable for Node SSR and HTML without client JavaScript. Neither entry injects the public CSS automatically.
Chrome inputs and derivation
The stylesheet exposes four inheriting color inputs. Set them on a wrapper or on an individual dashboard when a page needs a different chrome palette:
| Variable | Default | Used for |
|---|---|---|
--zdtp-dashboard-light-bg | #f8fafc | Light page and shell background |
--zdtp-dashboard-light-fg | #182131 | Light primary text and foreground |
--zdtp-dashboard-dark-bg | #151b24 | Dark page and shell background |
--zdtp-dashboard-dark-fg | #edf2f7 | Dark primary text and foreground |
The dashboard declares these four names as inherited values so an ancestor can override them without being shadowed by the component. --zdtp-dashboard-bg and --zdtp-dashboard-fg select the light or dark pair with light-dark(). Muted text and borders use color-mix() between that pair (58% foreground for muted text, 16% light / 22% dark foreground for borders). Card backgrounds mix 20% white into light backgrounds and 8% black into dark backgrounds. Diagnostic, focus, ruler, bar, sample, and checkerboard colors are also derived in the stylesheet from light-dark() and these chrome values. The dashboard root stays transparent so the host page controls the surrounding surface.
Mode dependence and row regions
Mode dependence belongs to individual rows and then propagates through every declared reference. The dashboard uses one parser, splitLightDark(), for a top-level light-dark(light, dark) value. Detection has this precedence:
item.modesis used when present.A semantic
{ literal: { light, dark } }override is used next.A top-level
light-dark(a, b)initem.defaultis parsed next.A row that references a mode-dependent row becomes mode-dependent too.
The selected mode displays the corresponding side. mode="host" keeps the pair as light-dark(light, dark) and lets the browser select the side from the inherited scheme. A malformed or nested expression is not treated as a mode pair; the authored declaration remains and no side is guessed.
The dependence check is per row, so a tier can contain both kinds. The inventory partitions each non-empty tab and tier by row: the mode-dependent region comes first and uses mode for its specimens; the mode-independent region follows and uses chrome. Original tab, tier, and row order is preserved within each region. include="mode-dependent" or include="mode-independent" selects one side of that visible partition. Filtering does not remove hidden declarations needed by references, and counts and diagnostics describe the visible rows.
Declared values
The input contract is declared defaults, not live or persisted panel state. It uses item defaults, colorExtras.semanticDefaults for the selected mode, and explicit colorExtras.baseDefaults for base-role rows. Named scheme presets and editor initialization are not applied. Pill defaults preserve item.default.
References resolve against declared item IDs and actual cssVar names, including reference tiers and cross-tab color ramps. Rows keep their declared value and expose CSS/reference text. Missing or ambiguous references, duplicate variables, cycles, and unsafe values remain visible with diagnostics instead of a misleading preview. Notes-only tabs are omitted; notes HTML is never injected. Ordering follows the input tabs, tiers, and items.
Preview choices and context
DashboardPreviewKind is 'bar' | 'size' | 'line-height' | 'family' | 'weight' |
'radius' | 'duration' | 'color' | 'shadow' | 'text'. Selection uses previewOverrides[cssVar], then TierConfig.preview, then a color sample for color-editor rows or text for other rows. duration and text keep the readable value without an animated or visual sample. previewBase can supply the font-size token for line-height samples when present and resolved.
Chrome appearance follows chrome: 'light' (the default) and 'dark' fix its appearance, while 'host' inherits the host's effective color-scheme. For 'host', the host must set color-scheme on an ancestor. The dashboard uses no media query, so an explicit application theme switch takes precedence over the OS preference.
Inventory specimens still own their color-scheme from mode, with known variables declared inside the preview inventory. Changing chrome does not change per-mode defaults or specimen schemes. Dashboard chrome uses its own CSS custom properties and never reads inventory tokens. Instances do not write host variables to :root or subscribe to panel changes.
CSS expressions are preserved, not universally computed or validated as every possible CSS property grammar. The browser supplies units, fonts, viewport, and other layout context. Missing external variable dependencies suppress the sample and display a diagnostic. Unsafe resource-bearing expressions are not previewed, and URL/mask assets are not loaded. Text is escaped by Preact.
Include referenced tiers when embedding a subset. Use an ordinary static Preact render for no-client-JavaScript output; hydration remains the host's choice.
Composition recipes
To make one inventory follow the surrounding page, set both chrome and mode to host. The host must set color-scheme on an ancestor:
<TokenDashboard
tabs={tokenTabs}
chrome="host"
mode="host"
title="Page-following tokens"
id="page-following"
/>For a three-instance reference, render the dependent rows once for each fixed mode and render the independent rows once. This keeps every mode-dependent row available in both snapshots while avoiding a duplicate independent inventory:
<TokenDashboard tabs={tokenTabs} include="mode-dependent" mode="light" title="Light-dependent tokens" id="tokens-light" />
<TokenDashboard tabs={tokenTabs} include="mode-dependent" mode="dark" title="Dark-dependent tokens" id="tokens-dark" />
<TokenDashboard tabs={tokenTabs} include="mode-independent" chrome="host" title="Shared tokens" id="tokens-shared" />Each instance owns one local declaration scope. Give instances distinct id values when they need to be linked from page navigation; IDs are never generated automatically. A wrapper can customize the four chrome inputs for just one instance:
<div style="--zdtp-dashboard-light-bg: #fff7ed; --zdtp-dashboard-light-fg: #7c2d12; --zdtp-dashboard-dark-bg: #1c1917; --zdtp-dashboard-dark-fg: #fed7aa">
<TokenDashboard tabs={tokenTabs} chrome="host" mode="host" title="Warm chrome" />
</div>The dashboard's internal buildDashboardModel helper now accepts an options object when its implementation needs both settings: buildDashboardModel(tabs, { mode: 'dark', include: 'mode-dependent' }). The positional buildDashboardModel(tabs, 'dark') overload remains available for compatibility; use the options form in internal integrations so the include filter is explicit. It is not a separate package dashboard export.
Layouts for spacing, color, and typography
Spacing (bar) uses wide rows with aligned ruler origins. Nonnegative px or rem lengths, unitless zero, and resolved direct local aliases get an actual-size sample. Ticks mark 8 CSS px, with major ticks every 64 CSS px. The browser sizes rem against the host root font size; the dashboard does not assume a conversion. Large lengths scroll inside the focusable ruler instead of shrinking or clamping. Zero has zero width. Negative lengths, em, percentages, calc() and other unsupported expressions retain their declaration with a ruler-unavailable explanation. Missing references also retain their diagnostics.
A nonsemantic, non-reference tier whose source items are all colors becomes a discrete palette strip. Stops stay in declared order, with every label and value visible; narrow containers scroll horizontally. Grouping uses tier structure, not name matching or generated intermediate colors. Semantic and reference tiers keep independent color samples. Per-variable preview overrides remain authoritative and retain each token's slot and order, including mixed overrides within a strip.
size, family, weight, and line-height use wide, multiline specimens with auto height outside palette strips. Overrides inside a palette retain their stop slot. The baseline is 18px text with 1.6 line height; each sample changes only its intended property. A resolved previewBase can supply the font size of a line-height sample. Font families use locally available fonts and their CSS fallbacks; the dashboard does not download fonts.
previewText supplies one static passage for all typography samples in an instance. Its default is longer English/Japanese prose. Newlines and white space are preserved, text is escaped, and an explicit empty string stays empty. Long text wraps; unusually large glyphs can scroll locally without scaling. There is no built-in editable text workbench or connection to panel state.