Theming & CSS
Every color, radius, and font in the shell resolves through prefixed
CSS custom properties declared in @dreamlake/dockit/styles.css. The
--doc-template- prefix isolates the shell from the consuming app's
own tokens; restyling the shell is overriding variables — no component
edits.
The consumer stylesheet
A dockit site owns exactly one CSS file. This site's is the whole recipe:
Line by line:
@import "tailwindcss"boots Tailwind v4 — notailwind.config.js, everything is CSS-first.@import "@dreamlake/dockit/styles.css"pulls in the shell's@themetoken block, dark-mode overrides, and component styles. Order matters: the library must come after tailwindcss and before your own overrides.- Your
@sourcelines point Tailwind at the directories where your markup uses utility classes, so those utilities get generated. - The library's stylesheet carries its own
@source "./"at the top. Because@sourceresolves relative to the file it appears in, and the file ships asdist/styles.css, that line makes Tailwind scan the package's compiled JS indist/— classes used only inside dockit components are always emitted, without you listing the package yourself.
Color tokens
Declared in an @theme block, so each also mints Tailwind utilities
(bg-doc-template-bg, text-doc-template-ink, …):
| Token | Light | Role |
|---|---|---|
--color-doc-template-bg | #fffefa | Page background |
--color-doc-template-panel | #fcfbf7 | Cards, footer panels |
--color-doc-template-rail | #fcfbf7 | Sidebar / rail background |
--color-doc-template-code | #faf8f1 | Code block surface |
--color-doc-template-ink | #1a1a1a | Primary text |
--color-doc-template-muted | #6b6b6b | Secondary text |
--color-doc-template-faint | rgb(0 0 0 / 0.08) | Hairline borders |
--color-doc-template-faint-strong | rgb(0 0 0 / 0.16) | Stronger borders |
--color-doc-template-chip | rgb(0 0 0 / 0.04) | Chip fills |
--color-doc-template-search | #f5f4f0 | Search field fill |
--color-doc-template-selected | #d9e6f7 | Active sidebar link |
--color-doc-template-accent | #23aaff | Links, active TOC, highlights |
--color-doc-template-accent-soft | rgb(35 170 255 / 0.09) | Accent washes |
--color-doc-template-warn | #d68b3a | Warnings, dev-mode dot |
--color-doc-template-warn-soft | rgb(214 139 58 / 0.10) | Warning washes |
--color-doc-template-rail-stroke | #d8d4c8 | TOC rail stroke |
Radii: --radius-doc-template (10px) and --radius-doc-template-sm
(6px).
Dark mode
A [data-theme='dark'] block re-declares the same custom properties —
every utility and inline style swaps instantly, with zero re-render.
The attribute is stamped on <html> by:
- the FOUC-safe inline script in the server-rendered head (first paint), and
ThemeProviderafterwards (user choice,systemtracking, cross-tab sync) — see ThemeToggle below.
A dark: Tailwind variant is wired to the same attribute for your own
pages. Shiki code colors are dual-theme (github-light /
github-dark) via CSS variables, so code follows along.
Fonts
| Token | Stack | Used for |
|---|---|---|
--font-doc-template-ui | Inter Tight, ui-sans-serif, … | Body, headings, links |
--font-doc-template-mono | Fira Code, ui-monospace, … | Code, chips, section labels, breadcrumbs |
The server renderer emits a single Google Fonts <link> loading Inter
Tight + Fira Code (the org-wide mono font).
Re-branding walkthrough
Restyling the shell is a stanza in your app.css, after the
library import. Override the light values on :root and the dark
values on [data-theme='dark']:
Every component — sidebar selection, TOC highlight, links,
chips — re-resolves through the variables; there
is nothing else to touch. If
you swap a font stack, remember to also load the webfont (the
renderer's default <link> only fetches Inter Tight and Fira Code).
ThemeToggle
The theme control comes in two variants, chosen by the themeToggle
field in Site config:
'cycle'(default) — a single button that steps light → system → dark, with a small spring animation on the icon swap.'segmented'— the three-button slider from the uikit/dreamlake docs: every theme visible at once, a pill indicator sliding under the active one, inactive icons leaning ±18°.
This site is configured with 'segmented', so that is what the topbar
shows. Here is another toggle, live — both stay in sync because they
share the same ThemeProvider state:
<ThemeToggle /> takes no props — the variant is site-level config,
not a per-instance choice. It must render inside the shell (or any
ThemeProvider) — on its own it falls back to inert context defaults.
How theme state flows
ThemeProvider(mounted by the Layout) keeps the choice in localStorage underdoc:theme, synced across tabs and across every consumer of the hook.- The provider stamps
data-theme="light" | "dark"on<html>; every color token above re-resolves instantly. - On first paint, a tiny inline script in the server-rendered
<head>reads the same key before hydration, so a dark-mode reader never sees a light flash (FOUC-safe).