Storybookについて調べてみました。

目次

  • はじめに
  • Storybookとは
  • メリット
  • 導入方法
  • サンプルの解説
  • アドオンの紹介
  • おわりに

はじめに

初めまして。 株式会社スタメンのフロントエンドグループでエンジニアをしている神尾です。 普段は弊社が運営しているエンゲージメントプラットフォームTUNAGの開発をしています。

今回の記事では、フロントエンドの開発で使用されるStorybookのメリットや導入方法、使い方についてお話したいと思います。

Storybookとは

  • UIコンポーネントの管理・テストをすることが出来るオープンソースツール。
  • サンドボックス環境を構築し、その環境下でコンポーネントの挙動や表示を確認できる他、カタログのようにコンポーネントを一目で見ることができる。
  • React、Vue、Angularなどの主要なJSフレームワークで導入でき、利用範囲も広い。

などの特徴があります。

メリット

  • UIコンポーネントのカタログとして視覚的に確認できることでエンジニアとデザイナーの認識の齟齬を無くすことが出来る。
  • カタログから探すことが出来るので、再利用したい時にすぐに調べることが出来る。
  • コードの変更が即時に画面に反映されるため、開発作業が素早く行える。
  • UIの変更に対して、ビジュアルリグレッションテストをすることができる。

Reactでの導入方法

# Storybookのサンプルアプリを作成
$ npx create-react-app react-storybook-sample

# 作成したサンプルアプリに移動
$ cd react-storybook-sample

# Storybookをインストール
$ npx -p @storybook/cli sb init

上記のコマンドを実行するとpackage.jsonにStorybookに必要なパッケージが追加・インストールされ、フォルダが作成されます。

下記は、作成されるフォルダの一部を抜粋しています。

- .stories/
 - main.js
 - preview.js
 
- src/
 - assets/
 - button.css
 - Button.js
 - Button.stories.js
 - その他サンプルのコンポーネント

ここまで正しくインストールできたら下記のコマンドを実行して、画像のように表示されたら準備完了です。 (自動的に表示されない場合はhttp://localhost:6006/にアクセスしてみてください。)

# StoryBookを起動する。
$ yarn storybook

画面左側には、Storybookに登録されているコンポーネントのリストが表示されており、右側では、コンポーネントが視覚的に確認することができます。

f:id:kannoo:20210517153506p:plain

サンプルの解説

Button.js

import React from 'react';
import PropTypes from 'prop-types';
import './button.css';

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 = {
  primary: PropTypes.bool,
  backgroundColor: PropTypes.string,
  size: PropTypes.oneOf(['small', 'medium', 'large']),
  label: PropTypes.string.isRequired,
  onClick: PropTypes.func,
};

Button.defaultProps = {
  backgroundColor: null,
  primary: false,
  size: 'medium',
  onClick: undefined,
};

Button.stories.js

import React from 'react';

import { Button } from './Button';

export default {
  title: 'Example/Button', 
  component: Button, 
};

const Template = (args) => <Button {...args} />;

export const Primary = Template.bind({}); 
Primary.args = { 
  primary: true,
  label: 'Button',
};

export const Secondary = Template.bind({});
Secondary.args = {
  label: 'Button',
};

インストール時にサンプルとして、いくつかのコンポーネントとStoryが作成されています。 上記は、その中のひとつであるButtonコンポーネント(Button.js)とButtonコンポーネントをStoryBookに上げるためのファイル(Button.stories.js)です。 ここからButton.stories.jsでどのようにStorybookに表示させているかを見ていきます。

import { Button } from './Button';    // Storybookに表示させたいButtonコンポーネントをimport

export default {
  title: 'Example/Button',   // Storybookのディレクトリ・ファイル名
  component: Button,        // 対象のコンポーネントを指定
};

export defaultでは、Storybookのタイトルや対象のコンポーネントを定義しています。 ここで定義したファイル構成が実際にStorybook上での構成となります。

export default {
  args: {
    primary: true,
  },
};

また、上記のように書くことで全てのStoryに共通の引数を渡すことも出来ます。 今回の例では、これから定義する全てのButtonコンポーネントに対して primary: true が渡されることになります。 その他にもexport defaultでは、いくつかの設定が出来るので、詳しくはこちらの公式サイトをご覧ください。

const Template = (args) => <Button {...args} />;    // argsで引数を受け取って、Buttonに渡すTemplateを定義。

export const Primary = Template.bind({});   // 各StoryでTemplateをBindして再利用
Primary.args = {  // 引数を定義
  primary: true,
  label: 'Button',
};

export const Secondary = Template.bind({});
Secondary.args = {
  label: 'Button',
};

続いて、ここでは実際にStorybookに表示するPrimaryボタンとSecondaryボタンが定義されています。 初めに、argsで受け取った引数をButtonのコンポーネントに渡すTemplateを定義して、引数によって表示が異なるButtonで使いまわせるようにしています。 その後、Templateをbindしてargsに引数を定義し、Buttonコンポーネントに必要な引数が渡されPrimaryButtonが表示されます。

このようにすることで、下記の画像のようにButtonが表示されます。

f:id:kannoo:20210517153627p:plain

main.js

module.exports = {
  stories: ['../src/**/*.stories.js'],      // ロードするファイルを指定。
  "addons": [
    "@storybook/addon-links",    // StoryBookを拡張するアドオンを指定。
    "@storybook/addon-essentials",
    "@storybook/preset-create-react-app"
  ] 
}
  • main.jsでは、Storybookにロードするファイルを指定している他、いくつかアドオンがデフォルトで追加されています。
  • アドオンをインストール後は、main.jsに使用するアドオンを追加します。

アドオンの紹介

Viewport

  • Storybook上で、レスポンシブなデザインを確認できるアドオン。
  • デバイスを設定することで簡単に幅を変更できる。
  • コードの変更がすぐに反映されるため、カタログとしてだけでなく開発中においても、デバイス毎のデザインを確認する時にも便利。

f:id:kannoo:20210517153721p:plain

Controll

  • Storybook上で、コンポーネントに渡す引数を変更できるアドオン
  • コードを書き換えることなく画面上でlabelやbackgroundcolorなどを変更できる。

f:id:kannoo:20210517154038p:plain

おわりに

最後まで読んでいただきありがとうございます!

今回の記事では、Storybookとは?導入するメリットは?ということから、実際にどのように登録されているのかということをお話させていただきました。Storybookって聞いたことはあるけど、何か分からないという方が「便利そうだから試しにやってみようかな!」と思ってもらえたら嬉しいです。

スタメンでは一緒に働くエンジニアを募集しています。興味がある方は、ぜひ採用サイトからご連絡ください。お待ちしております!