Skip to content

Quickstart

Assumes an existing Storybook 10 project with the Vite builder. Install, register, author the first doc page.

One package pulls the whole surface: toolbar, preview decorator, useToken(), every MDX doc block, and the standalone ThemeSwitcher. Install it:

Terminal window
npm install -D @unpunnyfuns/swatchbook-addon

swatchbook-core, -blocks, and -switcher come along transitively. If you only need a slice (say, the switcher in a Docusaurus site), each is also published independently.

Peer requirements: Storybook 10.1+ on the Vite builder, React 18+, Node 24+.

Register the addon with an inline config in .storybook/main.ts:

.storybook/main.ts
import { defineMain } from '@storybook/react-vite/node';
export default defineMain({
framework: '@storybook/react-vite',
addons: [
{
name: '@unpunnyfuns/swatchbook-addon',
options: {
config: {
resolver: 'tokens/resolver.json',
cssVarPrefix: 'ds',
},
},
},
],
});

Opt the preview into the addon’s annotations (decorator, globals, CSS injection):

.storybook/preview.ts
import { definePreview } from '@storybook/react-vite';
import swatchbookAddon from '@unpunnyfuns/swatchbook-addon';
export default definePreview({
addons: [swatchbookAddon()],
});

Inline config is the primary path. To keep the config in its own file (useful when the same config is consumed by a CLI or CI lint outside Storybook), write a swatchbook.config.ts and point at it with options.configPath: '../swatchbook.config.ts'; see config reference for details.

Start Storybook:

Terminal window
npm run storybook

A single swatchbook icon button appears in the top toolbar. Clicking it opens a popover with preset pills, a color-format picker, and one dropdown per modifier in your resolver. A single theme modifier with Light / Dark contexts gives one dropdown; a mode × brand resolver gives two.

The addon’s blocks render against the tuple currently active in the toolbar. Drop one into an MDX file under your stories glob to confirm the wiring is live:

src/docs/Tokens.mdx
import { Meta } from '@storybook/addon-docs/blocks';
import { TokenNavigator } from '@unpunnyfuns/swatchbook-addon';
<Meta title="Docs/Tokens" />
# Tokens
<TokenNavigator initiallyExpanded={0} />

Open Docs / Tokens in the sidebar: the tree lists every token in your project and repaints when you flip an axis. From here it’s a question of how you want to present the catalog.

If you haven’t written a DTCG 2025.10 resolver, use the layered config form instead:

swatchbook.config.ts
import { defineSwatchbookConfig } from '@unpunnyfuns/swatchbook-core';
export default defineSwatchbookConfig({
tokens: ['tokens/**/*.json'],
axes: [
{
name: 'mode',
contexts: {
Light: ['tokens/themes/light.json'],
Dark: ['tokens/themes/dark.json'],
},
default: 'Light',
},
],
cssVarPrefix: 'ds',
});

Each context names an ordered list of file paths (or globs) that layer on top of the base tokens files for that context. See the config reference for the resolver vs layered trade-off.

Tokens render through two surfaces, both built from the same blocks. MDX doc pages put blocks inside prose: a usage guide, a rationale, a migration note. Stories put the catalog in the sidebar, add a Controls panel, and bring each view under the same interaction, a11y, and visual-regression runs as your component stories. Token docs in MDX and stories covers both.

Also worth a look: