defuss-shadcn / Guides / theming
Theming
The theme is defined by semantic tokens - CSS custom properties that match the tweakcn.com export format. Design a theme in the Theme Designer (or on tweakcn), load its :root and .dark blocks after default-semantic-tokens.css, and every component rethemes instantly.
On this page (11)
Design your own theme
The Theme Designer edits every token on this site's own components and its six example apps, live - colours for light and dark, Google Fonts, radius, shadows. Save it by name to this site's theme menu, or export the CSS for your project.
§Surface / Foreground pairs
Every surface token pairs with a foreground token for text/icons placed on it.
§Utility tokens
--border--input--ring§Radius scale
Set --radius to retheme all border radii. The derived values are computed from it.
--radiusbase (0.625rem)--radius-smradius − 4px--radius-mdradius − 2px--radius-lgbase (--radius)--radius-xlradius + 4px§Sidebar tokens
Full sidebar token set for sidebar-specific theming. Same surface/foreground pair convention.
§Chart tokens
Five chart colors for data visualization.
--chart-1--chart-2--chart-3--chart-4--chart-5§Typography tokens
Font stacks as CSS custom properties. Themes can override these to change typography globally.
--font-sans--font-serif--font-mono§Shadow scale
Theme-aware shadows available as CSS custom properties.
--shadow-2xs--shadow-xs--shadow-sm--shadow--shadow-md--shadow-lg--shadow-xl--shadow-2xl§Spacing & Tracking
Base units that control all spacing and letter-spacing utilities.
--spacing0.25rem (4px)--tracking-normal0em§Customization
There are two ways to customize the theme:
1. Swap the entire theme
Design the theme, export its :root and .dark CSS variable blocks, and load them after (or instead of) default-semantic-tokens.css. Every component updates instantly. Two tools write that shape:
- The Theme Designer (recommended) - built into these docs. You see the theme on this system's components while you design it: the whole site follows every edit, and a preview shows a sample of every section at once - or a whole example app (Admin Dashboard, Messenger, Issue Tracker, Notes & Docs, Status Page, Desktop) - and doubles as the editor: click a colour to change it. Contrast badges flag text that fails WCAG AA on its surface; the radius is the same in light and dark (as every theme here must be); any Google Font can be picked, and the export carries its
@import. Save a theme by name and it sits on top of this site's theme menu, in your browser - or import a tweakcn export and refine it here. - tweakcn.com - works too: its exports use the same token names, so they drop in unchanged. Its preview renders shadcn/ui's React components, not these, so check the result here (paste it into the designer's Import).
2. Override individual tokens
Add a stylesheet afterdefault-semantic-tokens.css and override specific variables:
<link rel="stylesheet" href="default-semantic-tokens.css"><style> :root { --primary: oklch(0.55 0.2 250); --primary-foreground: oklch(1 0 0); --radius: 0.5rem; }</style>§Theme files
Every tweakcn preset ships as a generated stylesheet in dist/theme/<id>.css - the same :root + .dark token shape as default-semantic-tokens.css. Link one instead of the token file to ship a fixed theme:
<!-- instead of theme/utils/default-semantic-tokens.css --><link rel="stylesheet" href="theme/claude.css" />...or load it at runtime on top of the token file - inserting a <link id="theme-css"> right after it re-themes every component instantly (later source order wins the cascade; the file's own .dark block keeps dark mode working, so no re-apply on toggle). The Theme Switcher component wraps exactly that mechanism in an accessible dropdown, with persistence (a df$.store.persisted store) and a State API. On this site the picker in the header does the same.
// the preset link sits right after the token file - later source order winsdf$('#theme-css').remove();df$('link[href$="default-semantic-tokens.css"]') .after('<link id="theme-css" rel="stylesheet" href="theme/claude.css">');// presets with fonts ship a resource sidecar - loadTheme() adds those <link>s toodf$.shadcn.loadTheme?.('claude');The preset files are generated from the docs' theme dataset (src/documentation/runtime/themes.ts) by scripts/build.ts - verify's theme files fresh gate keeps them in lockstep. For your own themes, export one from the Theme Designer (or tweakcn) and link it the same way.
§Dark mode
The theme file includes both :root (light) and .dark (dark) values. To toggle dark mode, add or remove class="dark" on the <html> element. Every token switches automatically - no per-component overrides needed. See the Dark Mode page for system preference detection, persisting the choice (a df$.store.persisted store), and a step-by-step toggle implementation.
Comments, ideas or improvements? Edit this page's source on GitHub