自分のReact PJにStorybook導入してみたいけど、なんかめんどくさそう...という方へ向けて、サクッと簡単に導入できるまでのステップを紹介します。
1.Storybookのインストール
まずnpx create-react-app ${React PJ名}
でReactのPJを作成、もしくは既存のReact PJを開き、以下のコマンドを叩くだけです。
$ npx storybook init
このコマンドを叩くと以下のようなdirが新たに作成されます。
React PJ/
├ + .storybook/
├ src/
├ + stories/
このうち.storybook
にはStorybookを動かすための基本的な設定が、stories
ディレクトリにはサンプルのStorybook用のコンポーネントファイルが格納されます。
2.フォルダ構成の設定(❎必須)
ここで、まずどんなフォルダ構成にするのかを考えましょう。
例えばデフォルトで作成されたstories
フォルダにstorybook関連のファイルだけ格納するのか、自分でcomponents
フォルダに格納したコンポーネント用ファイルにstorybook関連のファイルも格納するのか?
私の場合は後者にしてみました。
特にStorybookをデフォルトでインストールした状態でも動きますが、components
フォルダにしか格納しない予定なので、storyを読み込みにいくパスを変更しておきます。
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
"@storybook/preset-create-react-app"
],
"framework": "@storybook/react",
"core": {
"builder": "@storybook/builder-webpack5"
}
}
これを
module.exports = {
"stories": [
"../src/components/*.stories.@(js|jsx|ts|tsx)"
],
...
こうしてみました。
3.Storyの書き方の説明
今回はInput
というコンポーネントを作ってみました。
コンポーネントの方は特に普通にReactでやる通りに書けばOKです。
import React from 'react';
import PropTypes from "prop-types"
function Input({
labelName = "",
labelTitle = "",
inputType = "text",
value = "",
width = "300",
borderColor = "gray"}) {
return (
<div style={{display: 'flex', flexWrap: 'wrap', width: width}}>
<label
name={labelName}
style={{marginBottom: 10, width: width}}>
{labelTitle}
</label>
<input type={inputType} value={value} style={{border: `1px solid ${borderColor}`}}/>
</div>)
}
Input.propTypes = {
labelName: PropTypes.string,
labelTitle: PropTypes.string,
inputType: PropTypes.string,
value: PropTypes.string,
width: PropTypes.number,
borderColor: PropTypes.string,
}
export default Input
次に、Story用にButton.stories.jsx
を書きます。
基本的にコンポーネントファイル+コンポーネント用のstoryファイルをセットで書きます。
またstory用のファイルは コンポーネント名.stories.js(x) というファイル名にする必要があります。
import React from 'react';
import Input from './Input';
// まず、以下export default内にコンポーネントの基本情報を書きます。
// 1. title: ここに書いた内容がStorybook画面でフォルダ構成として表示されます。例えば以下の場合、`Example/Button`とした場合Exampleというフォルダ(まとまり)以下にButtonというコンポーネントが表示されます。
// 2. component: ここで設定するコンポーネント名
// 3. argTypes: これは特に必須ではないのですが、コンポーネントファイルに書いたPropTypesや、デフォルト値を上書きすることができます。
export default {
title: "Input",
component: Input,
argTypes: {
width: {type: 'number', defaultValue: 500}
}
}
// Templateとして、ここにどんなパターンのコンポーネントを書くのか、その元となるテンプレートを書きます。
const Template = ({ ...args }) => (
<Input {...args}/>
)
// 以下、Templateを使って、色々なパターンのPropsなどを渡したスタイルなどを定義できます。
// ここではわかりやすいように、とりあえずtextのインプットと、パスワード用のインプットを作ってみました。
export const TextInput = Template.bind({})
TextInput.args = {
labelName: "",
labelTitle: "Title",
inputType: "text",
value: "",
flex: true,
borderColor: 'pink'
}
export const PasswordInput = Template.bind({})
PasswordInput.args = {
labelName: "",
labelTitle: "Password",
inputType: "password",
value: "",
flex: true,
borderColor: 'blue'
}
4.Storybookを立ち上げてみる
さて、ここまで書けたらnpm run storybook
をします。
すると、localhost:6006
にStorybookが立ち上がりました。
下の方にControls
というタブが見えていますが、ここに直接値を渡すことでコンポーネントの見た目を動的に変えてみることができます。
例えば、value
の隣のインプットに文字を入れると、コンポーネント内のInputに値が表示されます。
次に、画面上部のDocs
タブを開きます。
すると、コンポーネントファイルのPropTypesで設定した型の設定が反映されています。
これでStorybookが簡単に設定出来ました。
次回以降は、テストなど詳しい設定についても書いていきたいと思っています。