🦁
StoryBookを仕様書として使う
StoryBookとは
コンポーネントの開発・テスト・管理を行うためのOSSツールです。コンポーネントのコードや見た目を一元化して共有・参照することができます。また、アクセシビリティテストやビジュアルテストなどを行うこともできます。
今回はStoryBookをUIの仕様書として使う手順をまとめます。
前提知識
Docs
UIコンポーネントのドキュメントです。コンポーネントの引数やバリエーション(story)、またその説明を一覧することができます。
story
UIコンポーネントの特定の状態を表現したものです。具体的には、コンポーネントが特定の引数を受け取ったときの振る舞いや見た目を記述します。
使い方
1. AutoDocsの設定
StoryBookにはDocsを自動生成してくれる機能があります。
preview.ts
にtags: ['autodocs']
を設定することで、各コンポーネントに自動生成設定を施す必要がなくなります。
preview.ts
import type { Preview } from '@storybook/your-renderer';
const preview: Preview = {
...
+ tags: ['autodocs'],
};
export default preview;
2. StoryBookのためのコードを記述
Docs
簡単なドキュメントはStoryBookが自動作成してくれます。しかし、コンポーネントやプロパティの詳細な説明書きはないため、ドキュメンテーションコメント(/** コメント */
)を用いて説明を追加していきます。
Button.tsx
import { FC } from 'react';
import './button.css';
export interface ButtonProps {
/**
* ページ上で主要な役割をするボタンかどうか
*/
primary?: boolean;
/**
* ボタンの背景色
*/
backgroundColor?: string;
/**
* ボタンの大きさ
*/
size?: 'small' | 'medium' | 'large';
/**
* ボタンの使用の可否
*/
disable?: boolean;
/**
* ボタンの内容
*/
label: string;
/**
* click ハンドラを設定
*/
onClick?: () => void;
}
/**
* ユーザにアクションを実行してもらうためのコンポーネント
*/
export const Button: FC<ButtonProps> = ({
primary = false,
size = 'medium',
disable = false,
backgroundColor,
label,
...props
}) => {
const mode = primary
? 'storybook-button--primary'
: 'storybook-button--secondary';
const disableClass = disable ? 'storybook-button--disable' : '';
return (
<button
type="button"
className={[
'storybook-button',
`storybook-button--${size}`,
mode,
disableClass,
].join(' ')}
style={{ backgroundColor }}
{...props}
>
{label}
</button>
);
};
このように説明書きを追加することで、以下のような説明付きのドキュメントが作成されます。
story
取りうる状態を、[コンポーネント名].stories.ts
に記述します。
Docs同様、ドキュメンテーションコメントを用いて説明を追加することができます。
Button.stories.ts
import type { Meta, StoryObj } from '@storybook/react';
import { fn } from '@storybook/test';
import { Button } from './Button';
const meta = {
// コンポーネントのタイトル
title: 'Example/Button',
// 適用するコンポーネント(importしているコンポーネント)
component: Button,
// 引数の振る舞い
// これを指定することで、StoryBookのUI上で引数の値を動的に調整できるようになる。
// 自動推論されるので省略可能
argTypes: {
backgroundColor: {
control: 'color',
},
},
// 関数をスパイする
args: { onClick: fn() },
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
// 以下にstoryを記述する
// ここで記述した通りにStoryBookのUI上でコンポーネントが表示される
/**
* プライマリーカラーのボタン
*/
export const Primary: Story = {
args: {
primary: true,
label: 'Button',
},
};
/**
* セカンダリーカラーのボタン
*/
export const Secondary: Story = {
args: {
label: 'Button',
},
};
/**
* 大きなサイズのボタン
*/
export const Large: Story = {
args: {
size: 'large',
label: 'Button',
},
};
/**
* 小さなサイズのボタン
*/
export const Small: Story = {
args: {
size: 'small',
label: 'Button',
},
};
/**
* 使用不可のボタン
*/
export const Disabled: Story = {
args: {
primary: true,
size: 'medium',
label: 'Button',
disable: true,
},
};
3. StoryBookを起動
npm run storybook
4. 画面の立ち上がりの確認
このような画面が表示されます。
詳細な仕様書を作ることができました!
storyファイルの場所
コンポーネントファイルと同じディレクトリに配置することがよいかもしれません。
Accessibilityテスト
コンポーネントを登録した際には、Accesibilityテストを通過しているか確認するのが望ましいです。
参考
Discussion