This guide explains how to set up and use Storybook for KanaDojo UI component development.
- Overview
- Installation
- Configuration
- Creating Stories
- Running Storybook
- Best Practices
- Available Stories
Storybook is a tool for developing UI components in isolation. It provides:
- Visual testing of components in different states
- Documentation automatically generated from stories
- Interactive development environment
- Component gallery for the design system
Install Storybook with the following command:
npx storybook@latest init --type react --builder vite --yesThis will:
- Install dependencies (may take a few minutes)
- Create
.storybook/configuration directory - Add example stories to
stories/ - Update
package.jsonwith scripts
After installation, these scripts are available:
# Start Storybook development server
npm run storybook
# Build static Storybook for deployment
npm run build-storybook
# Run Storybook tests
npm run test-storybookStorybook is configured to use the same path aliases as the main application:
// .storybook/main.ts
import path from 'path';
const config = {
// ...
viteFinal: async config => {
return {
...config,
resolve: {
alias: {
'@': path.resolve(__dirname, '../'),
'@/features': path.resolve(__dirname, '../features'),
'@/shared': path.resolve(__dirname, '../shared'),
'@/core': path.resolve(__dirname, '../core'),
},
},
};
},
};The preview file (.storybook/preview.ts) sets global parameters for all stories:
import type { Preview } from '@storybook/react-vite';
const preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
// Add more global parameters here
},
};
export default preview;Stories are written in TypeScript and follow this pattern:
// components/ui/button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './button';
const meta = {
title: 'UI/Button',
component: Button,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
variant: {
control: { type: 'select' },
options: ['default', 'destructive', 'outline', 'secondary', 'ghost'],
},
},
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {
children: 'Button',
variant: 'default',
},
};
export const Primary: Story = {
args: {
children: 'Primary Button',
variant: 'default',
},
};Place story files next to the components they document:
shared/components/
├── ui/
│ ├── button.tsx # Component
│ └── button.stories.tsx # Stories
├── dialog.tsx
└── dialog.stories.tsx
Use the title property to organize stories in the sidebar:
// UI components
export const MyComponent = { title: 'UI/MyComponent' };
// Feature components
export const GameCard = { title: 'Features/Game/GameCard' };
// Layout components
export const Header = { title: 'Layout/Header' };Use args to define default props and argTypes to configure controls:
const meta = {
component: MyComponent,
args: {
variant: 'default',
size: 'medium',
},
argTypes: {
variant: {
control: { type: 'select' },
options: ['small', 'medium', 'large'],
description: 'The size variant of the component',
},
onClick: { action: 'clicked' },
},
};Use decorators to wrap stories with additional context:
const meta = {
component: MyComponent,
decorators: [
(Story) => (
<div style={{ padding: '2rem' }}>
<Story />
</div>
),
],
};Start the Storybook development server:
npm run storybookThis will:
- Start a local server (typically at
http://localhost:6006) - Watch for changes and hot reload
- Show component documentation
Build a static version for deployment:
npm run build-storybookOutput is saved to storybook-static/ and can be deployed to any static host.
Run Storybook tests in CI:
npm run test-storybookKeep stories co-located with components:
components/
└── MyComponent/
├── index.ts # Exports
├── MyComponent.tsx
├── MyComponent.stories.tsx # Stories here
└── MyComponent.test.tsx # Tests here
Document important component states:
export const States: Story = {
args: {
// Default state
},
};
export const Loading: Story = {
args: {
loading: true,
},
};
export const Disabled: Story = {
args: {
disabled: true,
},
};
export const Error: Story = {
args: {
error: 'Something went wrong',
},
};Configure controls for better DX:
argTypes: {
variant: {
control: { type: 'select' },
options: ['primary', 'secondary', 'tertiary'],
},
size: {
control: { type: 'radio' },
options: ['small', 'medium', 'large'],
},
onAction: { action: 'action' },
children: { control: 'text' },
},Add stories for edge cases:
export const LongText: Story = {
args: {
children: 'Very long text that might cause wrapping issues...',
},
};
export const SpecialCharacters: Story = {
args: {
children: 'Special chars: àéïõü 中文 にほんご 🎉',
},
};Currently documented components:
| Component | Location | Status |
|---|---|---|
| Button | shared/components/ui/button.stories.tsx |
✅ Complete |
| AlertDialog | shared/components/ui/alert-dialog.stories.tsx |
📝 To Do |
| Dialog | shared/components/ui/dialog.stories.tsx |
📝 To Do |
| Select | shared/components/ui/select.stories.tsx |
📝 To Do |
Storybook includes these addons:
| Addon | Purpose |
|---|---|
@storybook/addon-essentials |
Controls, actions, docs, viewport |
@storybook/addon-interactions |
Interaction testing |
@storybook/addon-a11y |
Accessibility testing |
@storybook/addon-docs |
Auto-generated docs |
If you see errors about missing modules:
npm installIf TypeScript errors occur:
# Restart TypeScript server in your IDE
# Or regenerate types
npm run i18n:generate-typesEnsure CSS is imported in preview:
// .storybook/preview.ts
import '../app/globals.css';