zudo-doc
GitHub repository

Type to search...

to open search from anywhere

Component Tokens

Created Jun 29, 2026Takeshi Takatsudo

The --zdc-* override seams — a public rebrand API for component styling (typography, shape, layout) you cannot reach by editing the component.

zudo-doc ships its layout and content components from the @takazudo/zudo-doc package. Those components hardcode their Tailwind utility classes — the doc-page title is literally <h1 class="text-heading font-bold">. That is the right call for a shipped component (see Component First Strategy), but it leaves consumers a question: how do you re-style a component you do not own?

The --zdc-* component tokens are the answer. They are a small, curated set of CSS custom properties that the package exposes as supported override seams — redefine one in your own :root and the matching component restyles across every route, with no !important and no eject.

The component-library ownership inversion

The usual component-first guidance is: the component is the abstraction, so if you want a different look, change the component. That works when the component is yours. Here it is not — it lives in node_modules/@takazudo/zudo-doc. Editing it means forking or ejecting the whole component, and trying to override it from the outside means fighting unlayered Tailwind-utility specificity with !important. Both are bad doors.

So the conclusion inverts. When you cannot edit the component file, the component token becomes your scope. Instead of reaching into the component, you redefine a value the component already reads. The component-first rule still holds inside the package; the --zdc-* surface is simply the seam it exposes outward.

Info

This is the opposite of "component-first, so skip component tokens." That shortcut assumes you own the component. For a packaged component you do not own, the component token is the only clean override point — so it is exactly where your customization belongs.

The one-line override

Every --zdc-* token is redefined the same way: declare it on :root. There is no API to import, no component to wrap, and no build step to run.

src/styles/global.css
:root {
  --zdc-doc-title-font: "Georgia", serif;
  --zdc-doc-title-weight: 800;
}

That single block rebrands the page-title <h1> on every page — doc pages, the home page, tag pages, the versions page — because :root is global and the backing rule is unlayered with enough specificity to beat the component's own utility class. No !important is needed, and you never touch the package source.

The defaults are deliberately invisible. Each token falls back to an existing design token or inherit (for example --zdc-doc-title-weight defaults to var(--font-weight-bold), matching the original font-bold utility), so a project that overrides nothing renders byte-for-byte as before. You only opt in to the tokens you actually want to change.

How it fits the three-tier token story

zudo-doc's tokens are organized into three tiers, each referencing only the tier above it: raw palette values (Tier 1) flow into semantic tokens (Tier 2), which feed component tokens (Tier 3). See Design System and Color for the full model.

--zdc-* tokens are Tier 3 — component-scoped. But unlike the internal Tier-3 color variables inside .zd-content (which are private implementation details you should not reference), --zdc-* tokens are published as a public API: stable, documented names you are meant to redefine. They extend the same proven pattern the color system already uses, where redefining a --zd-* palette token in :root re-themes the whole site. --zdc-* brings that one-line :root override model to component typography.

Token reference

The tables below list every --zdc-* token. They are sourced directly from the registry, so they always match what the package ships.

Tokens are split by rendering surface. Content tokens target the .zd-content prose area (shipped in @takazudo/zudo-doc/content.css). Chrome tokens target the app shell — sidebar navigation, TOC, and card grids (shipped in @takazudo/zudo-doc/features.css).

Content tokens

TokenComponentDefaultWhat it controls
--zdc-doc-title-fontdoc-titleinheritFont family of the page-title <h1> (doc-page titles plus the home, tag, and versions page titles that share text-heading).
--zdc-doc-title-weightdoc-titlevar(--font-weight-bold)Font weight of the page-title <h1>.
--zdc-doc-title-trackingdoc-titlevar(--tracking-normal)Letter spacing of the page-title <h1>. Defaults to var(--tracking-normal) (resolves to normal — byte-identical to the browser default).
--zdc-doc-h2-fontheading-h2inheritFont family of content <h2> headings.
--zdc-doc-h2-weightheading-h2var(--font-weight-bold)Font weight of content <h2> headings.
--zdc-doc-h2-trackingheading-h2var(--tracking-normal)Letter spacing of content <h2> headings.
--zdc-doc-h3-weightheading-h3var(--font-weight-bold)Font weight of content <h3> headings.
--zdc-doc-h4-weightheading-h4var(--font-weight-semibold)Font weight of content <h4> headings.
--zdc-doc-prose-fontdoc-prosevar(--font-sans)Font family of the .zd-content prose area. Redefine to use a distinct body font for doc content; headings with --zdc-doc-*-font: inherit inherit this value.
--zdc-doc-link-decorationcontent-linkunderlineText decoration of styled content links (the text-accent underline path in ContentLink; excludes block and hash-link variants). Set to none to remove underlines from content links.
--zdc-admonition-radiusadmonition0 var(--radius-DEFAULT) var(--radius-DEFAULT) 0Border radius of admonition/callout blocks. Defaults to the current value (0 on the left edges, --radius-DEFAULT on the right — the flush-left accent look).
--zdc-admonition-border-widthadmonition4pxWidth of the admonition left accent border.

Chrome tokens

TokenComponentDefaultWhat it controls
--zdc-card-radiuscard-gridvar(--zdc-surface-radius, var(--radius-DEFAULT))Border radius of nav/doc card anchors (doc-card-grid, nav-card-grid, category-nav). Chains through --zdc-surface-radius — see below.
--zdc-content-max-widthdoc-content-bandclamp(50rem,75vw,90rem)Max width of the doc reading column (sidebar-present case). The no-sidebar 80 rem variant is handled separately by [data-zd-nosidebar] in features.css.
--zdc-toc-widthtoc280pxWidth of the desktop Table of Contents right rail.
--zdc-nav-active-indicator-colornav-activevar(--color-fg)Background color of the active sidebar nav link (the inversion fill that marks the current page).
--zdc-nav-active-weightnav-activevar(--font-weight-medium)Font weight of the active sidebar nav link.

The --zdc-surface-radius meta-knob

--zdc-surface-radius is not a registry entry — it has no backing CSS rule of its own. It exists as a link in the default chain of --zdc-card-radius:

var(--zdc-card-radius, var(--zdc-surface-radius, var(--radius-DEFAULT)))

Set --zdc-surface-radius in :root and every surface that opts into the chain rounds together — without overriding each token individually:

src/styles/global.css
:root {
  --zdc-surface-radius: 0.75rem; /* rounds all surfaces at once */
}

This is the "round everything at once" knob. Individual surfaces can still break out by setting their own --zdc-card-radius (or future surface tokens) directly; the meta-knob only wins when the per-surface token is unset.

Tip

Font family (-font), font weight (-weight), and letter spacing (-tracking) are kept as separate, granular tokens rather than a single font shorthand. The CSS font shorthand resets every sub-property it does not name (size, line-height, style), which would both break the byte-identical default and reduce control — you could not change the weight without restating the family and size. Independent knobs stay independent tokens.

Not editable in the Design Token Panel

These are source-level override seams, not live-tweakable values.

Note

The Design Token Panel edits the semantic spacing, font, size, and color tokens live in the browser. The --zdc-* component tokens are deliberately outside its scope: they are component-owned rebrand seams you set once in :root (in src/styles/global.css), not knobs you drag at runtime. If you are looking for a token in the panel and cannot find it, it is a component token — set it in your stylesheet instead.

Discovering the full set

The registry that backs the table above is the typed source of truth. It is exported from the package as @takazudo/zudo-doc/component-tokens (the COMPONENT_TOKENS array), so the complete, current list — token name, component, default, and description — is discoverable and type-checked in code, not just in this page. When the package adds a new component token, it appears in that export, and this reference is regenerated from it.

Revision History

Takeshi TakatsudoCreated: 2026-06-30T02:36:43+09:00Updated: 2026-06-30T06:01:01+09:00

AI Assistant

Ask a question about the documentation.