Storybookとは?
storybookとはUIのカタログを作るツール
各componentのUIやpropsに応じた挙動の確認、component単位でドキュメントを用意することを可能にしてくれます。
Storyファイルを作成する
metaとは?
MetaオブジェクトはStorybookのコンポーネントのメタデータを定義するために使用されます。
Metaオブジェクト
component: Storybookで表示するコンポーネント自体を指定します。(index.tsx
(storyを作成したいcomponent)からimportして指定)
title: コンポーネントのタイトルを指定します。
description: コンポーネントの説明やドキュメントを指定します。
args: コンポーネントのデフォルトのプロパティ(引数)の値を指定します。これにより、Storybook上でコンポーネントを表示する際にデフォルトのプロパティ値が設定されます。
ここで指定した値は、storybookで描画されるもの。
このプロパティに指定された値は、仮の値であり、実際のアプリケーションの実装には直接的な影響を与えません。
※ controlsと関連している
argTypes: コンポーネントの各プロパティ(引数)のコントロールを指定します。これにより、Storybook上でコンポーネントのプロパティを調整するコントロールが表示されます。
parameters: コンポーネントに関連する追加のパラメータを指定します。
Storybookのカンバス上の背景色やアドオンの設定など、
Storybookの機能や外観を制御するための設定情報を指定する部分。
例えば、backgrounds パラメータを使用すると、カンバスの背景色を変更できる。
※ メタデータ: データのためのデータ
const meta: Meta<typeof StatusMessage> = {
component: Button,
title: 'Components/Button', // Storybook上でのディレクトリを分けることができる
argTypes: {
onClick: { action: 'clicked' }, // onClickプロパティのコントロールを指定し、クリックイベントを記録する
label: { control: 'text' }, // labelプロパティのコントロールを指定し、テキストを入力できるようにする
disabled: { control: 'boolean' }, // disabledプロパティのコントロールを指定し、チェックボックスで有効/無効を切り替えられるようにする
},
parameters: {
docs: {
description: {
component: 'コメントがDocに反映される',
},
},
backgrounds: {
values: [
{ name: 'red', value: '#f00' }, // canvasの背景色を赤に設定
{ name: 'green', value: '#0f0' }, // canvasの背景色を緑に設定
{ name: 'blue', value: '#00f' }, // canvasの背景色を青に設定
],
},
layout: "centered", // ストーリーズを描画する位置を調整できる (padded, fullscreen)
},
}
Metaオブジェクトにargsを設定して共通のプロパティを記述する手間を省く
Metaオブジェクトにargsを設定することで、各ストーリーに共通のデフォルトプロパティを提供できます。これにより、各ストーリーで共通のプロパティを記述する手間を省くことができます。
また、ストーリーで内容を上書きすることができる
const meta = {
title: "Button",
component: Button,
tags: ["autodocs"],
argTypes: { handleClick: { action: "clicked" } },
args: {
children: "Submit",
},
} satisfies Meta<typeof Button>;
export const SubmitLarge: Story = {
args: {
// children: "Submit", 不要 🙆♀️
size: "lg",
},
};
export const Cancel: Story = {
args: {
children: "Cancel", // 内容を上書きできる 🙆♀️
size: "lg",
},
};
他のストーリーの記述を引用する方法
スプレッドを使用して他のストーリーからargs(スタイルなど)を引き継ぐことができる
export const Plus: Story = {
args: {
children: "+1",
bgColor: "add",
size: "roundWidth",
round: "round",
},
};
export const Minus: Story = {
args: {
...Plus.args, // スプレッドを使用して他のストーリーからargs(スタイルなど)を引き継ぐことができる
children: "-1",
},
};
argTypesってなに
ArgTypesはargsの振る舞いを指定するためのもの
Storybook上でのコンポーネントの振る舞いを確認するために定義する引数
これを設定することで、storybook上でのコントロールでの操作が可能になる
(実際のコンポーネントの実装や使用には直接的な影響はありません)
import { RadioButton } from './index'
import type { Meta, StoryObj } from '@storybook/react'
const meta: Meta<typeof RadioButton> = {
component: RadioButton,
tags: ['autodocs'],
argTypes: {
onClick: { action: 'clicked' }, // onClickプロパティに対して、クリックイベントを記録するコントロールを表示
label: { control: 'text' }, // labelプロパティに対して、テキスト入力としてのコントロールを表示
checked: { control: 'boolean' }, // checkedプロパティに対して、チェックボックスで有効/無効を切り替えられるコントロールを表示
disabled: { control: 'boolean' }, // disabledプロパティに対して、チェックボックスで有効/無効を切り替えられるコントロールを表示
},
}
export default meta
type Story = StoryObj<typeof RadioButton>
export const Unchecked: Story = {
args: {
label: 'label 1',
checked: false,
},
}
export const Checked: Story = {
args: {
label: 'label 2',
checked: true,
},
}
export const Disabled: Story = {
args: {
label: 'label 3',
checked: false,
disabled: true,
},
}
・argTypesのpropsはストーリーズに依存する
ArgTypesはstorybook上で操作したい値があるときに定義する
例えば、ボタン機能を実装するとした場合、
onClickの挙動を確認するために、
argTypes: {
onClick: { action: 'clicked' },
}
を設定する
labelの値の確認が必要、ということなら、
argTypes: {
label: { control: 'text' },
}
を設定する
ドロップダウンのコントロールを確認したかったら、
argTypes: {
variant: { control: 'select', options: ['primary', 'secondary', 'success', 'danger'] }, // ドロップダウンで選択できるコントロールを表示
},
を設定する
argTypesの中身 > actionキー とは
actionsキーは、ストーリー内で受け取ったデータをイベントハンドラ(コールバック)の引数として表示するために使用されます。
▼ onClickという引数がアクション
であることをStorybookに伝えることができます:
argTypes: {
onClick: { action: 'clicked' },
}
addonについて
addonとは
追加の機能や機能拡張を提供するためのもの
actionとは (addon-actions)
actionsとは
コンポーネント内で発生するイベントをキャプチャして、その情報をドキュメント内で表示するためのアドオン
コンポーネントの特定のイベントに対してアクションを追加し、そのアクションが発生するとドキュメント内でイベントの詳細情報が表示される
import { action } from '@storybook/addon-actions'
:
:
export const Preview: Story = {
render: () => {
const [isOpen, setIsOpen] = useState(false)
const onSubmit = async (value: FormValues) => {
await sleep(1000).then(() => {
action('onSubmit')(value)
})
}
return (
<Button onClick={onSubmit}>
},
actionをonSubmitの中に記述することで、storybook上でログを確認できる
withActionsとは (addon-actions)
withActionsとは
Storybook のアドオンの一つで、コンポーネントのアクション(イベント)を記録して表示するためのデコレータ(Decorator)
コンポーネントのインタラクションやイベントがどのように動作するかを視覚的に確認できるようになる
ボタンがクリックされたときやフォームが送信されたときなどのイベントが記録され、ドキュメント上でそれらのイベントがどのように発生するかを確認できる
記録されたイベントを通じて、コンポーネントが予想通りに動作するかどうかをテストすることができる
const meta: Meta<typeof Button> = {
component: Button,
tags: ['autodocs'],
decorators: [withActions as Decorator],
parameters: { actions: { handles: ['click .mantine-Menu-item'] } },
}
argTypesの中身 > control とは
argTypes: {
label: { control: 'text' },
}
コンポーネントのさまざまな状態や振る舞いを簡単に確認でき、コンポーネントの開発やテストを迅速に進めることができる
例えば、backgroundColor: {control: 'color'}
と設定すると、storybook上で背景色の変更ができ、確認できるようになったり、label: { control: 'text' }
とすると、storybook上でlabelの値を変更できるようになったりする
// Button.stories.ts|tsx
// Replace your-framework with the name of your framework
import type { Meta } from '@storybook/your-framework';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
component: Button,
argTypes: {
variant: {
options: ['primary', 'secondary'],
control: { type: 'radio' },
},
},
};
export default meta;
ラジオボタンで色選択が可能になる
argTypesの出番
・storybookのcontrolerを使用して、該当のstoryを操作したい時。
・基本、argsの実装で良い(初期値を指定すれば、持っている値をradio buttonで実装してくれる)
・「select」や「radio」で指定したいのにargsで指定してもそうならない場合に、argTypesを使えば良い。
Annotation
example and table featuring all available controls
Data Type | Control | Description |
---|---|---|
boolean | boolean | Provides a toggle for switching between possible states. |
number | number | Provides a numeric input to include the range of all possible values. |
argTypes: { even: { control: { type: 'number', min: 1, max: 30, step: 2 } }} | ||
range | Provides a range slider component to include all possible values. | |
argTypes: { odd: { control: { type: 'range', min: 1, max: 30, step: 3 } }} | ||
object | object | Provides a JSON-based editor component to handle the object's values. |
Also allows edition in raw mode. | ||
argTypes: { user: { control: 'object' }} | ||
array | object | Provides a JSON-based editor component to handle the values of the array. |
Also allows edition in raw mode. | ||
argTypes: { odd: { control: 'object' }} | ||
file | Provides a file input component that returns an array of URLs. | |
Can be further customized to accept specific file types. | ||
argTypes: { avatar: { control: { type: 'file', accept: '.png' } }} | ||
enum | radio | Provides a set of radio buttons based on the available options. |
argTypes: { contact: { control: 'radio', options: ['email', 'phone', 'mail'] }} | ||
inline-radio | Provides a set of inlined radio buttons based on the available options. | |
argTypes: { contact: { control: 'inline-radio', options: ['email', 'phone', 'mail'] }} | ||
check | Provides a set of checkbox components for selecting multiple options. | |
argTypes: { contact: { control: 'check', options: ['email', 'phone', 'mail'] }} | ||
inline-check | Provides a set of inlined checkbox components for selecting multiple options. | |
argTypes: { contact: { control: 'inline-check', options: ['email', 'phone', 'mail'] }} | ||
select | Provides a drop-down list component to handle single value selection. | |
argTypes: { age: { control: 'select', options: [20, 30, 40, 50] }} | ||
multi-select | Provides a drop-down list that allows multiple selected values. | |
argTypes: { countries: { control: 'multi-select', options: ['USA', 'Canada', 'Mexico'] }} | ||
string | text | Provides a freeform text input. |
argTypes: { label: { control: 'text' }} | ||
color | Provides a color picker component to handle color values. | |
Can be additionally configured to include a set of color presets. | ||
argTypes: { color: { control: { type: 'color', presetColors: ['red', 'green'] } }} | ||
date | Provides a datepicker component to handle date selection. | |
argTypes: { startDate: { control: 'date' }} |
option / mapping の使用方法
オブジェクト、配列、Elementなどを扱うstoryの設定について
mapping
Type: { [key: string]: { [option: string]: any } }
セレクタなどを使用して描画を切り替える方法
Elementのパターン
export const Preview: Story = {
argTypes: {
body: {
// 該当のpropsに対して、どんな値を入れてテストするかoptionを設定できる
options: ['short', 'long'],
mapping: {
short: <div>content</div>,
long: (
<div>
<p>long content long content long content</p>
<p>long content long content long content</p>
<p>long content long content long content</p>
</div>
),
},
},
},
args: {
title: 'title',
body: <div>Content</div>,
},
}
・optionsはドロップダウンメニューで表示される値のリストを指定できる
この場合、['short', 'long']
と指定されているため、ドロップダウンにはshortとlongの2つの選択肢が表示されます。
・mappingは選択肢ごとに表示したい内容を指定するオブジェクト
例えば、optionsがshortの場合に表示する内容は<div>content</div>
となる
これにより、StorybookのUI上でbodyプロパティに対して、ドロップダウンで異なる選択肢を選ぶことができ、選択された値に応じてコンポーネントの描画が変わることが確認できる
プリミティブ型(文字列など)をセレクタで描画を切り替える方法
以下のように、controlを追加して、selectやradioなど、任意の値を記述できるようにします
export const Preview: Story = {
argTypes: {
title: {
control: {
type: 'select', ⭐️
},
options: ['proceeding', 'pending'],
mapping: {
proceeding: ['続行してください'],
pending: ['しばらくお待ちください'],
},
},
content: {
control: {
type: 'select',
},
options: ['proceeding', 'pending'],
mapping: {
proceeding: [
'フォームを入力し、保存ボタンを押下してください',
],
pending: [
'処理が完了するまでしばらくお待ちください',
],
},
},
},
args: {
title: '続行してください',
content: 'フォームを入力し、保存ボタンを押下してください',
isProcessing: true,
},
}
controlを設定することで、セレクタ(ドロップダウン)やラジオボタンなどのコントロールを提供することができます
typeを指定することで、表示するコントロールの種類を指定できる
selectを指定した場合、optionsに記述された値がドロップダウンに表示される
mappingを使用することで、選択された値に応じて表示する内容を指定できる
controlの設定について
非プリミティブ型
└ 設定不要
非プリミティブ型(オブジェクト、配列、JSXなど)の値を操作したい場合は、controlを直接使用することはできない
プリミティブ型
└ 設定必要