storybookを理解する
この記事ではReact, Typescriptをベースにstorybookの全体像に触れていきます。
「storybook、名前は聞いたことある」というレベル感の人に対して、実務でstorybookを使う上での下地を作ることが目的です。そのため、「細かい」と判断した部分は割愛させてもらってます。(あくまで下地)
基本的には公式ドキュメントがベースになっていますので、詳しい説明は公式ドキュメントを確認してください。
storybookとは
storybookとはUIのカタログを作るツールで、2022年現在、フロントエンド開発において必要不可欠です。
各componentのUIやpropsに応じた挙動の確認、component単位でドキュメントを用意することを可能にしてくれます。
導入方法
コマンドを打ちましょう。
npx sb init
下記コマンドでpreview画面が起動します。
yarn storybook
そうするとインストールした時に作成された雛形がpreviewで表示されるでしょう。
storyの書き方
storybookにcomponentを登録していくには、storyを記述する必要があります。
stories.js | ts | jsx | tsx | mdx
の拡張子に設定することで、ファイルはstoryとして認識されます。
また、これらは開発環境のみでプロダクション環境ではbundleされません。
Component Story Format(CSF)
Component Story Formatは推奨されているstoryの書き方です。ESmoduleをベースとして記述している書き方でstory fileはdefault export か named exportから構成されています。(ESmoduleについての説明は割愛)
CSFの詳しい概要はこちら。
具体的な書き方
最初にstoryのmetadataをdefault exportする必要があります。
export default {
title: 'Button',
component: Button,
} as ComponentMeta<typeof Button>;
titleをui-componens/Button
みたいにすると階層を表現できます。
その下に各componentを記述していきます。
// 小文字だとButton配下にファイルが作成されない。
// titleとcomponentの名前を同じにしたい場合、小文字にするとよい。
export const button: ComponentStory<typeof Button> = () => <Button />;
// ベースcomponentを元にcomponentをButton配下に表示させたい時に変数の命名を変更させる。
export const basic: ComponentStory<typeof Button> = () => <Button />;
export const primary: ComponentStory<typeof Button> = () => <Button />;
propsに応じてcomponentを複数表示するには
templateとしてbindするとPropsに応じたcomponentを表示しやすくなります。
↓このようなpropsを必要とするcomponentがあるとします。
import React from "react";
type Props = {
text: string;
};
const Button: React.VFC<Props> = ({ text }) => {
return <button style={{ padding: "5px" }}>{text}</button>;
};
export default Button;
↓bindしてあげる。
/* eslint-disable react/react-in-jsx-scope */
import Button from "./Button";
import { ComponentStory, ComponentMeta } from "@storybook/react";
export default {
title: "example/Button",
component: Button,
} as ComponentMeta<typeof Button>;
const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />;
export const Primary = Template.bind({});
Primary.args = { text: "this is Primary" };
export const Secondary = Template.bind({});
Secondary.args = { text: "this is Secondary" };
そうすると、画像のようにstorybookからinputで表示されるでしょう。
もちろんこれは編集することができ、propsを適当な値にして表示を気軽に確認できます。
イベントの書き方
さらにaddonでActionをつかってonClickを定義してあげましょう。
propsにonClickを含めます。
const Button: React.VFC<Props> = ({ text, onClick }) => {
return (
<button style={{ padding: "5px" }} onClick={onClick}>
{text}
</button>
);
};
export default Button;
@storybook/addon-actions
をmain.jsでaddonの配列に追加したのちに、先ほどのstoryにpropsを追記します。
import { action } from "@storybook/addon-actions";
const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />;
export const Primary = Template.bind({});
Primary.args = { text: "this is Primary", onClick: action("clicked") };
export const Secondary = Template.bind({});
Secondary.args = { text: "this is Secondary", onClick: action("clicked") };
そうするとbuttonをクリックした際にactionが走り、下ペインから確認することができます。
parameaterを使う
metadataの中にparameterを入れることでstoryのトップレベルに設定を追記することができます。
公式ドキュメントと同じように設定してみましょう。
背景色を設定することができることが確認できます。
export default {
title: "example/Button",
component: Button,
parameters: {
backgrounds: {
values: [
{ name: "red", value: "#f00" },
{ name: "green", value: "#0f0" },
{ name: "blue", value: "#00f" },
],
},
},
} as ComponentMeta<typeof Button>;
decoratorsを使う
metadataの中にdecoratorsを追記することで、storyがレンダリングされる際に任意の要素でwrapすることができます。
公式ドキュメントでは下記のようにdiv要素でmarginを設定しています。
decorators: [
(Story) => (
<div style={{ margin: '3em' }}>
<Story />
</div>
),
],
decoratorは範囲によって記述する場所が異なるので、公式ドキュメントを参照してください。
Docsの書き方
各componentに応じたdocumentを書くことができます。documentの書き方(表示のされ方)はmetadataから設定します。
component及びsubcomponent
metadataにて、componentとsubcomponentを設定するとドキュメントでpropsがtable形式で表示されます。
export default {
title: "example/Buttons",
component: ButtonGroup,
subcomponents: { Button },
} as Meta;
mdx
mdxを使ってmarkdownライクに記述することもできます。
詳しくは公式ドキュメントを見て下さい。
docsのカスタマイズ
ドキュメントページに表示される項目を自分でカスタマイズすることもできます。
export default {
title: 'Button',
component: Button,
parameters: {
docs: {
// ここで表示される項目、その順番などを変更することができる
page: () => (
<>
<Title>タイトル</Title>
<Subtitle>サブタイトル</Subtitle>
<Primary />
<ArgsTable story={Button} />
<Description markdown={markdown} />
</>
),
},
},
};
const markdown = `
# markdownn
> testtest
`;
Buildをする
個人的に下記オプションを覚えておけばいいと思います。
-
-s
で静的ファイルを設定 -
-o
で出力先ディレクトリを設定
npx sb init
でプロジェクトを立ち上げた場合はpackage.jsonに初期buildコマンドが追加されているので、自分のプロジェクトに応じて修正してください。
また、buildしたファイルをpublishする際には、vercel,Netlify,S3が使えます。公式ドキュメントを確認してみてください。
tests
chromaticへhosting及びvisual test
UIのvisual testについては以前記事にしたので、そちらを参照してください。
a11y test
yarn add --dev @storybook/addon-a11y
でアクセシビリティのaddonを追加してください。
main.jsの設定に追記して、yarn storybook
をすれば、preview画面から確認することができます。
細かい設定方法は公式ドキュメントを確認してください。
interaction test
user eventをstoryに組み込み確認したい場合は、@storybook/testing-library
を使いましょう。
ここでは詳しく触れません。公式ドキュメントを確認してください。
ドキュメントではFormでemailとpasswordを入力させて、UIの確認をしています。
各種設定方法
必要に応じて、公式ドキュメントを参照しましょう。
細かいので、ここでは割愛します。
storybook公式の情報
公式のブログがあります。こちらをみていれば最新の情報はキャッチアップできます。
CSF3.0というコンセプトは魅力的なのでチェックするといいかもしれません。
まとめ
奥が深いので軽く全体を抑えてから、その他addonや細かい設定に手を出すと良さそうです。
また、今後storybookがプラットフォームとなって様々なツールが連携し、フロントエンドの開発が発展するでしょう。
Discussion