React Storybook

Storybook for React

UI コンポーネントのサンドボックス環境を簡単に作れる。
自作 UI ライブラリのデモページを作りたいときに便利。

参考:

インストール

https://storybook.js.org/docs/guides/guide-react/
ココの手順通りに。

# storybookと依存関係を入れる
yarn add -D @storybook/react babel-loader @babel/core

# すでに入れている場合は不要
# UIライブラリを作るときはpeerDependenciesで入れる
yarn add -P react react-dom

package.jsonに追記する。
デフォルトだとランダムなポートでサーバが起動するが、ポートを指定する場合は-p <ポート番号>を書けばいい。

{
  "scripts": {
    "storybook": "start-storybook -p 2220"
  }
}

CLI で使えるオプションについて:
https://storybook.js.org/docs/configurations/cli-options/

.storybook/config.jsを作る。

import { configure } from "@storybook/react";

function loadStories() {
  const req = require.context("../stories", true, /\.stories\.js$/);
  req.keys().forEach(filename => req(filename));
}

configure(loadStories, module);

stories/index.jsを作る。

import React from "react";
import { storiesOf } from "@storybook/react";
import { Button } from "@storybook/react/demo";

storiesOf("Button", module)
  .add("with text", () => <Button>Hello Button</Button>)
  .add("with emoji", () => (
    <Button>
      <span role="img" aria-label="so cool">
        😀 😎 👍 💯
      </span>
    </Button>
  ));

ローカルサーバ起動

yarn storybook

Markdown を使う

TypeScript を使う

https://storybook.js.org/docs/configurations/typescript-config/

必要な依存関係を入れる。

yarn add -D typescript \
  ts-loader \
  @types/storybook__react \
  @storybook/addon-info \
  react-docgen-typescript-loader

tsconfig.jsonに以下の設定を追記する。

{
  "compilerOptions": {
    // `src`はコンポーネントを配置しているルートディレクトリに置き換える
    "rootDirs": ["src", "stories"]
  },
  // 除外したいディレクトリがあればここに書く
  "exclude": ["usage"]
}

props 情報を自動生成するためには名前付きエクスポートでコンポーネントを作成する必要がある

Sass を使う

Sass を使うコンポーネントライブラリに Storybook を導入する場合に必要。

yarn add sass-loader node-sass -D

.storybook/webpack.config.jsにローダーの設定を追記する。

const { resolve } = require("path");

module.exports = async ({ config, mode }) => {
  config.module.rules.push({
    test: /\.scss$/,
    use: [
      "style-loader",
      "css-loader",
      {
        loader: "sass-loader",
        options: {
          // @import '@material/ripple/mixins';
          // のようにnode_modules内のscssをimportしている場合はこれが必要。
          // ただしビルドが遅くなるので不要な場合は消したほうがいい。
          includePaths: [resolve(__dirname, "../node_modules/")]
        }
      }
    ]
  });
  return config;
};

headタグをカスタマイズする

追加でフォントや CDN の css を読み込みたい場合などに。

.storybook/preview-head.htmlファイルを作成し、以下のように書けばいい。

<link
  rel="stylesheet"
  href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css"
/>

コンポーネント表示エリアをカスタマイズする

デフォルトだと padding がなくて微妙なので css を書いてそれを読み込んでみる。

.storybook/story.cssを書く。(ファイル名はなんでもいい)

#story-root {
  padding: 2rem;
}

#story-rootはコンポーネントが表示される div 領域なので、この id に対してスタイルをあてればいい。

その後、.storybook/config.tsで css を読み込む。

import "./story.css";

便利なアドオン

knobs

https://github.com/storybookjs/storybook/tree/release/3.4/addons/knobs

インストール。

yarn add -D \
  @types/node \
  @types/react \
  @storybook/addon-knobs

.storybook/addons.jsに以下を追記する。

import "@storybook/addon-knobs/register";

.storybook/config.tsに以下を追記する。

import { withKnobs } from "@storybook/addon-knobs/react";
import { addDecorator } from "@storybook/react";

addDecorator(withKnobs);

stories/button.stories.tsxの例

import { text } from "@storybook/addon-knobs/react";
import { storiesOf } from "@storybook/react";
import * as React from "react";
import Button from "../src/components/Button";

const stories = storiesOf("Button", module);

stories.add("Button", () => <Button label={text("Label", "BUTTON")} />);

Storybook Addon Actions

https://github.com/storybookjs/storybook/tree/release/3.4/addons/actions

UI イベントのデータをログに表示できる。

インストール。

yarn add -D \
  @storybook/addon-actions \
  @types/storybook__addon-actions

Storybook Info Addon + react-docgen-typescript-loader

https://github.com/storybookjs/storybook/tree/release/3.4/addons/info

インストール。

yarn add -D \
   @storybook/addon-info \
   @types/storybook__addon-info \
   react-docgen-typescript-loader

.storybook/config.tsに以下を追記する。

import { setDefaults, withInfo } from "@storybook/addon-info";
import { addDecorator } from "@storybook/react";

addDecorator(withInfo);

// グローバルデフォルト設定
setDefaults({
  inline: true,
  header: false
});

.storyboo k/webpack.config.jsreact-docgen-typescript-loaderのローダーを追加する。
このローダーを追加することで props の表などが表示できるようになる。

const path = require("path");
const SRC_PATH = path.join(__dirname, "../src");
const STORIES_PATH = path.join(__dirname, "../stories");

const { dirname, join, resolve } = require("path");

module.exports = async ({ config, mode }) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    include: [SRC_PATH, STORIES_PATH],
    use: [
      {
        loader: require.resolve("ts-loader")
      },
      // Optional
      {
        loader: require.resolve("react-docgen-typescript-loader")
      }
    ]
  });
  config.resolve.extensions.push(".ts", ".tsx");

  return config;
};

あとは普通にストーリーを書くだけ。

import { text } from "@storybook/addon-knobs/react";
import { storiesOf } from "@storybook/react";
import * as React from "react";
import Button from "../src/components/Button";

storiesOf("Button", module).add("Button", () => <Button label="BUTTON" />);

GitHub Pages にデプロイする。

yarn add -D \
  gh-pages
yarn add -D \
  @storybook/storybook-deployer