Skip to content

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/core

Basic Setup ​

Step 1: Initialize Storybook ​

bash
npx storybook@latest init

Step 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 dropdown

Story-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 chromatic

Theme 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 ​

  1. Document all tokens with examples
  2. Show themes side-by-side for comparison
  3. Test contrast ratios in stories
  4. Version control token documentation
  5. Use consistent naming in stories
  6. Group related components and tokens
  7. Include responsive variants
  8. Test accessibility with each story

Deployment ​

Build Storybook ​

bash
npm run build-storybook

Host 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-static

Troubleshooting ​

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-storybook

Next Steps ​