Skip to content

Storybook基礎

Storybookは、UIコンポーネントを独立して開発・テスト・ドキュメント化するためのツールです。

問題のある開発プロセス:

// アプリケーション内でコンポーネントを開発
function App() {
return (
<div>
<Button>通常のボタン</Button>
<Button variant="primary">プライマリボタン</Button>
{/* 問題点:
- アプリケーション全体を起動する必要がある
- 他のコンポーネントに影響を受ける
- コンポーネントの状態を簡単に確認できない
- ドキュメントが別途必要
*/}
</div>
);
}

Storybookの解決:

// Storybookでコンポーネントを独立して開発
export default {
title: 'Components/Button',
component: Button,
};
export const Default = {
args: {
children: '通常のボタン',
},
};
export const Primary = {
args: {
variant: 'primary',
children: 'プライマリボタン',
},
};
// メリット:
// - アプリケーション全体を起動する必要がない
// - コンポーネントを独立して開発・テストできる
// - 様々な状態を簡単に確認できる
// - ドキュメントが自動生成される

メリット:

  1. 独立した開発: アプリケーション全体を起動せずにコンポーネントを開発
  2. 視覚的なテスト: 様々な状態を簡単に確認
  3. ドキュメント化: コンポーネントの使用方法を自動生成
  4. チーム協業: デザイナーと開発者の連携が容易
Terminal window
# ReactプロジェクトにStorybookを追加
npx storybook@latest init
# 手動インストール
npm install --save-dev @storybook/react @storybook/react-webpack5
npm install --save-dev storybook
Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
title: 'Components/Button',
component: Button,
tags: ['autodocs'],
argTypes: {
variant: {
control: 'select',
options: ['primary', 'secondary', 'danger'],
},
size: {
control: 'select',
options: ['small', 'medium', 'large'],
},
},
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Default: Story = {
args: {
children: 'Button',
},
};
export const Primary: Story = {
args: {
variant: 'primary',
children: 'Primary Button',
},
};
export const Secondary: Story = {
args: {
variant: 'secondary',
children: 'Secondary Button',
},
};
Button.tsx
import React from 'react';
interface ButtonProps {
variant?: 'primary' | 'secondary' | 'danger';
size?: 'small' | 'medium' | 'large';
children: React.ReactNode;
onClick?: () => void;
disabled?: boolean;
}
export const Button: React.FC<ButtonProps> = ({
variant = 'primary',
size = 'medium',
children,
onClick,
disabled = false,
}) => {
const baseStyles = 'font-semibold rounded transition-colors';
const variantStyles = {
primary: 'bg-blue-500 text-white hover:bg-blue-600',
secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300',
danger: 'bg-red-500 text-white hover:bg-red-600',
};
const sizeStyles = {
small: 'px-2 py-1 text-sm',
medium: 'px-4 py-2 text-base',
large: 'px-6 py-3 text-lg',
};
return (
<button
className={`${baseStyles} ${variantStyles[variant]} ${sizeStyles[size]}`}
onClick={onClick}
disabled={disabled}
>
{children}
</button>
);
};
Button.stories.tsx
import { expect, userEvent, within } from '@storybook/test';
import { Button } from './Button';
export const WithInteraction: Story = {
args: {
children: 'Click me',
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const button = canvas.getByRole('button');
await userEvent.click(button);
await expect(button).toHaveTextContent('Clicked!');
},
};
.storybook/preview.ts
export const decorators = [
(Story) => (
<div style={{ padding: '20px', backgroundColor: '#f5f5f5' }}>
<Story />
</div>
),
];
// グローバルパラメータ
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
};
Card.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Card } from './Card';
const meta: Meta<typeof Card> = {
title: 'Components/Card',
component: Card,
tags: ['autodocs'],
};
export default meta;
type Story = StoryObj<typeof Card>;
export const Default: Story = {
args: {
title: 'Card Title',
description: 'This is a card description',
image: 'https://via.placeholder.com/300',
},
};
export const WithAction: Story = {
args: {
title: 'Card with Action',
description: 'This card has an action button',
image: 'https://via.placeholder.com/300',
actionLabel: 'Learn More',
onAction: () => alert('Action clicked!'),
},
};
export const Loading: Story = {
args: {
loading: true,
},
};

Storybookのポイント:

  • 独立した開発: アプリケーション全体を起動せずにコンポーネントを開発
  • 視覚的なテスト: 様々な状態を簡単に確認
  • ドキュメント化: コンポーネントの使用方法を自動生成
  • チーム協業: デザイナーと開発者の連携が容易

Storybookは、コンポーネント駆動開発(CDD)を実現するための強力なツールです。