皆さんこんにちは、GMOリサーチシステム部のダラーです。
GMOリサーチでは近頃フロントエンドにも力を入れ始めており、現在デザインチームと協力してデザインシステムを導入する検討をしています。(デザインシステムについてはまた別途)
このデザインシステムの導入にあたって、スタイルガイドと実際のUIコンポーネントを同期する必要があり、これに最適なツールとして有名なのはタイトルでも挙げた通りStorybookです。今回このStorybookを実際に取り入れる為に、機能や導入方法について調べた内容をこちらで共有したいと思います!
Storybookとは?
StorybookはUIコンポーネントを一元管理することが出来るツールです。
npmやyarnなどを使って導入が簡単に行うことができ、また全ての機能が無料です。こうしたツールを使うと、作成したコンポーネントを一挙にstorybook上からUIを確認することが出来たり、またstorybook上からコンポーネントに対してパラメータを渡すことが出来る為、実際に色々なパラメータを渡して画面上からテストが出来ます。
実はこうしたツールはStorybookだけではなく、色々と無料のものが存在しているのですが(UxPin, React Bluekit, Doczなどなど)、やはり世界的にも人気なのはStorybookだと思います。
Storybookのメリットとデメリット
さて、それでは具体的にStorybookを使うことのメリットとデメリットについて見ていきたいと思います。
Storybookのメリット
・コンポーネントを一覧で画面から確認できること
これは先にも述べた通りですが、フォルダにあるコンポーネントを全て画面から一挙に見ることが出来ます。特にコンポーネントが大量にあるような場合は、コードのみからUIを予想するのは難しいですが、それが直感的に分かるようになります。
・UIの動きや機能を担保することが可能になること
Storybookでは画面上から実際にデザインを確認するだけでなく、ユーザ一動作を行ったときの挙動についても画面上から確認することが出来る上、テストを書くことも出来ます。その為、コンポーネントに変更があった際にもこの機能を使って動作や機能を担保することが可能になります。
・UIの一貫性を保ちやすくなること
コンポーネントを一画面から全て確認できることのメリットは、それぞれのコンポーネン トの見た目の一貫性を保ちやすくなることです。特にデザインシステムを導入しようとしている場合、Storybookを導入することでスタイルガイドと同期して、デザインが一貫性を持っていることを担保しやすくなります。
Storybookのデメリット
・管理が大変
Storybookのデメリットの最大のポイントがこれです。というのも、Storybookを使うためにはコンポーネントごとに .stories.jsx
という形式でstoriesファイルを作成する必要があって、さらにここにstoriesを定義する必要があります。
コンポーネントに修正が入った場合、storiesも修正しないといけないかもしれません。コンポーネントは実際のアプリケーションで使うからきちんとやるという場合でも、忙しすぎてStorybookにまで手が回らなかったら、どんどんレガシー化することが避けられない、というデメリットはありそうです。(実際そういった話をよく見かけます)
・導入が大変
もし何か今からコンポーネントライブラリを0から作成しようとしていて、Storybookも一緒に導入、というのであれば良いのですが、もし既にあるコンポーネントライブラリに導入しようと思った場合、この労力は図り知れません…
一応こうした手間を省くため、いくつか導入用にコンポーネント単位でstoriesファイルを自動生成してくれるようなライブラリもあるため、こうしたライブラリを使うことも出来ます。ただ、テンプレートのような自分でパターンを決定するような内容は、自分でコードを書く必要があるので、その辺りの手間はやはり避けられないかなとは思います。
Storybookの導入方法
Storybookを導入する方法はいたって簡単です。
1 |
$ npx storybook init |
npmなら:
1 |
$ npm run storybook |
yarnなら:
1 |
yarn storybook |
で立ち上がります。簡単ですね!
導入すると、まずStorybookのサンプルコードがいくつかデフォルトで作成されるため、これを読めば大体なんとなくの構造がつかめてくると思います。
番外:MUIを使うときの方法
GMOリサーチではReactコンポーネントを書く際に、MUIライブラリをベースにコンポーネントを作っているのですが、MUIを使ったコンポーネントをStorybookに反映させたいときは追加で設定がいくつか必要になります。
サンプルアプリを試しに作成してみたのですが、その際にはこちらの記事を参考にさせていただいて設定しました。
基本的なstoryの書き方
これはStorybookを導入した時にインストールされるサンプルファイルですが、これを参考にざっくりとstoryの書き方や、これがどうStorybook上に反映されるかについて見ていきたいと思います。
まず、Reactの方のcomponentファイルです。
Button.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
/** * Primary UI component for user interaction */ export const Button = ({ primary, backgroundColor, size, label, ...props }) => { const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary'; return ( <button type="button" className={['storybook-button', `storybook-button--${size}`, mode].join(' ')} style={backgroundColor && { backgroundColor }} {...props} > {label} </button> ); }; Button.propTypes = { /** * Is this the principal call to action on the page? */ primary: PropTypes.bool, /** * What background color to use */ backgroundColor: PropTypes.string, /** * How large should the button be? */ size: PropTypes.oneOf(['small', 'medium', 'large']), /** * Button contents */ label: PropTypes.string.isRequired, /** * Optional click handler */ onClick: PropTypes.func, }; Button.defaultProps = { backgroundColor: null, primary: false, size: 'medium', onClick: undefined, }; |
次にstoriesファイルです。
Button.stories.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export export default { title: 'Example/Button', component: Button, // More on argTypes: https://storybook.js.org/docs/react/api/argtypes argTypes: { backgroundColor: { control: 'color' }, }, }; // More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args const Template = (args) => <Button {...args} />; export const Primary = Template.bind({}); // More on args: https://storybook.js.org/docs/react/writing-stories/args Primary.args = { primary: true, label: 'Button', }; export const Secondary = Template.bind({}); Secondary.args = { label: 'Button', }; export const Large = Template.bind({}); Large.args = { size: 'large', label: 'Button', }; export const Small = Template.bind({}); Small.args = { size: 'small', label: 'Button', }; |
そして、これをローカルで立ち上げた時に見える画面がこちらです。
ここでExampleというフォルダの配下に、Buttonが表示されています。これはstoriesファイルのtitleに表示されている内容を反映しています。
また、storiesファイル内でPrimary, Secondary, Large, Smallというものをexportしていますが、このTemplate.bindを使って色々な種類のUIタイプを表示することが出来ます。
↓下のControlsに見えている属性の種類はButtonのPropTypesから取得しています。
Storybookの他社例について
Storybookを導入してみたいけど、まず他社がどんな使い方でやっているのかを知りたいという場合、こちらから有名なグローバル企業のStorybookを見ることが出来ます。
Add-onについて
Storybookでは沢山のAdd-onが用意されています。
有名なものでいえば、ダークモードやChromatic、Storyshotsなどでしょうか。こうしたAdd-onを使うことで、Storybookにプラスで様々な機能を使うことが出来ます。
いかがでしたでしょうか?
Storybook、是非試してみてください!