Storybook Integration with TokiForge
Integrate TokiForge design tokens with Storybook for interactive documentation and visual testing of themed components.
Installation
bash
npm install -D storybook @storybook/react @tokiforge/storybook @tokiforge/coreBasic Setup
Step 1: Initialize Storybook
bash
npx storybook@latest initStep 2: Configure TokiForge Integration
.storybook/main.ts
typescript
import type { StorybookConfig } from "@storybook/react-vite";
import { createTokensAddon } from "@tokiforge/storybook";
import { themeConfig } from "../src/config/tokens";
const config: StorybookConfig = {
stories: ["../src/**/*.stories.{js,jsx,ts,tsx}"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
createTokensAddon(themeConfig),
],
framework: {
name: "@storybook/react-vite",
options: {},
},
};
export default config;Step 3: Create Preview Configuration
.storybook/preview.tsx
typescript
import type { Preview } from "@storybook/react";
import { ThemeProvider } from "@tokiforge/react";
import { themeConfig } from "../src/config/tokens";
import "../src/styles/globals.css";
const preview: Preview = {
parameters: {
layout: "fullscreen",
tokens: {
config: themeConfig,
defaultTheme: "light",
},
},
decorators: [
(Story) => (
<ThemeProvider config={themeConfig}>
<Story />
</ThemeProvider>
),
],
};
export default preview;Using Design Tokens in Stories
Basic Story with Theme Support
typescript
// src/components/Button.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
import { Button } from "./Button";
const meta = {
title: "Components/Button",
component: Button,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Primary: Story = {
args: {
children: "Click me",
variant: "primary",
},
};
export const Secondary: Story = {
args: {
children: "Secondary",
variant: "secondary",
},
};
export const Disabled: Story = {
args: {
children: "Disabled",
disabled: true,
},
};Token Documentation Story
typescript
// src/tokens.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
const meta = {
title: "Design System/Tokens",
parameters: {
layout: "fullscreen",
},
} satisfies Meta;
export default meta;
export const Colors: StoryObj = {
render: () => (
<div className="p-8 space-y-8">
<h1 className="text-2xl font-bold">Color Tokens</h1>
<div className="grid grid-cols-4 gap-4">
<div>
<div
className="w-24 h-24 rounded-lg shadow-md"
style={{ backgroundColor: "var(--color-primary)" }}
/>
<p className="mt-2 text-sm font-medium">Primary</p>
</div>
<div>
<div
className="w-24 h-24 rounded-lg shadow-md"
style={{ backgroundColor: "var(--color-secondary)" }}
/>
<p className="mt-2 text-sm font-medium">Secondary</p>
</div>
</div>
</div>
),
};
export const Spacing: StoryObj = {
render: () => (
<div className="p-8 space-y-8">
<h1 className="text-2xl font-bold">Spacing Tokens</h1>
<div className="space-y-4">
{["xs", "sm", "md", "lg", "xl"].map((size) => (
<div key={size} className="flex items-center">
<div
className="bg-blue-500"
style={{
width: `var(--spacing-${size})`,
height: `var(--spacing-${size})`,
}}
/>
<span className="ml-4 font-mono text-sm">spacing.{size}</span>
</div>
))}
</div>
</div>
),
};
export const Typography: StoryObj = {
render: () => (
<div className="p-8 space-y-8">
<h1 className="text-2xl font-bold">Typography Tokens</h1>
<div className="space-y-4">
<div>
<p style={{ fontSize: "var(--font-size-sm)" }}>Small text</p>
<p className="text-xs text-gray-500">font-size-sm</p>
</div>
<div>
<p style={{ fontSize: "var(--font-size-md)" }}>Medium text</p>
<p className="text-xs text-gray-500">font-size-md</p>
</div>
<div>
<p style={{ fontSize: "var(--font-size-lg)" }}>Large text</p>
<p className="text-xs text-gray-500">font-size-lg</p>
</div>
</div>
</div>
),
};Theme Switching in Storybook
Manual Theme Selection
The TokiForge addon automatically adds theme controls to Storybook toolbar:
typescript
// Themes appear in the toolbar - no code needed!
// Select "Light", "Dark", etc. from the dropdownStory-Level Theme Override
typescript
// src/components/Card.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
import { Card } from "./Card";
export const DarkModeOnly: StoryObj = {
args: {
title: "Dark Mode Card",
},
parameters: {
tokens: {
theme: "dark", // Force dark theme for this story
},
},
};
export const AllThemes: StoryObj = {
args: {
title: "Multi-theme",
},
parameters: {
tokens: {
showAllThemes: true, // Display all theme variants
},
},
};Advanced Configuration
Custom Theme Controls
typescript
// .storybook/preview.tsx
import { themeConfig } from "../src/config/tokens";
export const parameters = {
tokens: {
config: themeConfig,
themes: {
light: {
label: "☀️ Light",
default: true,
},
dark: {
label: "🌙 Dark",
},
"high-contrast": {
label: "🔷 High Contrast",
},
},
},
};Custom Token Display
typescript
// .storybook/preview.tsx
export const parameters = {
tokens: {
config: themeConfig,
displayMode: "compact", // or 'detailed'
groups: {
colors: { label: "🎨 Colors" },
spacing: { label: "📏 Spacing" },
typography: { label: "✍️ Typography" },
},
},
};Testing Themes
Visual Regression Testing
bash
npm install -D @chromatic-com/storybook
npx chromatic init
npm run build-storybook
npx chromaticTheme Contrast Testing
Create a story to verify WCAG compliance:
typescript
// src/a11y.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
export const ContrastRatios: StoryObj = {
render: () => (
<div className="p-8 space-y-4">
<div
className="p-4 rounded"
style={{
backgroundColor: "var(--color-background)",
color: "var(--color-text)",
}}
>
<p>Primary text on background</p>
<small className="text-gray-500">Ratio: 7:1 (AAA)</small>
</div>
<div
className="p-4 rounded"
style={{
backgroundColor: "var(--color-primary)",
color: "white",
}}
>
<p>White text on primary</p>
<small>Ratio: 8.5:1 (AAA)</small>
</div>
</div>
),
};Component Documentation
Auto-generate Docs from Tokens
typescript
// src/tokens/index.stories.mdx
import { Meta, Canvas, Story } from '@storybook/blocks';
import { getTokensByCategory } from '@tokiforge/core';
<Meta title="Design System/Token Catalog" />
# Design Token Catalog
## Colors
All color tokens available in the design system:
<Canvas>
{getTokensByCategory('color').map((token) => (
<div
key={token.name}
style={{
display: 'flex',
alignItems: 'center',
gap: '1rem',
marginBottom: '1rem',
}}
>
<div
style={{
width: '100px',
height: '100px',
backgroundColor: token.value,
borderRadius: '8px',
border: '1px solid #ccc',
}}
/>
<div>
<p className="font-mono font-bold">{token.name}</p>
<p className="text-gray-500">{token.value}</p>
</div>
</div>
))}
</Canvas>Integration with Component Library
Shared Storybook Instance
typescript
// storybook/preview.tsx
import { ThemeProvider } from "@tokiforge/react";
import { themeConfig } from "@mycompany/design-tokens";
export const decorators = [
(Story) => (
<ThemeProvider config={themeConfig}>
<Story />
</ThemeProvider>
),
];Token Versioning
typescript
// storybook/main.ts
const tokiforgeAddon = createTokensAddon(themeConfig, {
version: require("@mycompany/design-tokens/package.json").version,
repository: "https://github.com/mycompany/design-tokens",
});Best Practices
- Document all tokens with examples
- Show themes side-by-side for comparison
- Test contrast ratios in stories
- Version control token documentation
- Use consistent naming in stories
- Group related components and tokens
- Include responsive variants
- Test accessibility with each story
Deployment
Build Storybook
bash
npm run build-storybookHost on Static Server
bash
# Vercel
vercel --prod
# Netlify
netlify deploy --prod --dir storybook-static
# GitHub Pages
npm run build-storybook
npx gh-pages -d storybook-staticTroubleshooting
Theme Not Switching
Ensure the decorator is applied:
typescript
// .storybook/preview.tsx
export const decorators = [
(Story) => (
<ThemeProvider config={themeConfig}>
<Story />
</ThemeProvider>
),
];Tokens Not Displaying
Check token format:
json
{
"themes": [
{
"name": "light",
"tokens": {
"color": {
"primary": { "value": "#007AFF", "type": "color" }
}
}
}
]
}Build Failures
Clear cache and rebuild:
bash
rm -rf node_modules/.cache
npm run build-storybookRelated Resources
Next Steps
- Explore Storybook best practices
- Set up visual testing
- Configure CI/CD integration