序章

Storybook は、コンポーネントのドキュメント化に使用できるユーザーインターフェイス(UI)ライブラリです。

注:この記事は、ストーリーブックの概要に基づいており、JavaScriptコンポーネントの整理と構築に使用する方法について説明しています。

この記事では、ReactとStorybookを使用してインタラクティブなUIコンポーネントを構築します。

Screenshot of the Storybook UI component dashboard.

チュートリアルの最後に、ストーリーブックをスタンドアロンアプリケーションとして展開し、スタイルガイドとして機能させます。

前提条件

このチュートリアルを完了するには、次のものが必要です。

このチュートリアルは、ノードv14.4.0、npm v6.14.5、react v16.13.1、および@storybook/reactv5.3.19で検証されました。

ステップ1—プロジェクトの設定

開始するには、新しいReactプロジェクトを作成する必要があります。このために、Reactアプリケーションのスキャフォールディングに最適なツールであるcreate-react-appを使用します。

  1. npx create-react-app storybook-app

次に、新しく作成されたプロジェクトディレクトリに移動します。

cd storybook-app

次のステップは、storybookパッケージをプロジェクトにインストールすることです。

  1. npx -p @storybook/cli sb init

このコマンドは、package.jsonファイルから使用しているフレームワークを自動的に検出し、そのフレームワークのストーリーブックバージョンをインストールできます。

両方のコマンドを実行した後、package.jsonファイルを開いてパッケージがインストールされているかどうかを確認することで、@storybook/reactの依存関係がインストールされていることを確認できます。その後、アプリケーションを実行し、Storybookを実行できます。

  1. npm start

Screenshot of the React welcome page.

  1. npm run storybook

Screenshot of the Storybook welcome page.

両方のコマンドを実行すると、ReactアプリとStorybookアプリの両方が異なるポートで実行されます。

手動で構成を追加する

上記の手順に従った場合は、すでに事前構成されています。 @storybook/reactパッケージを既存のReactプロジェクトにインストールした場合は、次の手順に従ってストーリーブックを設定する必要があります。

まず、Reactプロジェクトのルートディレクトリに.storybookフォルダーを作成し、次にconfig.jsというフォルダー内にファイルを作成して、次のコード行を追加します。

.storybook / config.js
import { configure } from '@storybook/react';

function loadStories() {
  require('../src/stories');
}

configure(loadStories, module);

上記のコードブロックはStorybookの構成であり、src/storiesディレクトリでストーリーを検索するようにStorybookに指示します。 まだ設定されていない場合は、そのフォルダを作成します。 srcフォルダー内に、storiesというフォルダーを作成します。 これは、ストーリーを作成するすべてのコンポーネントが最終的に配置される場所です。

注: Storybook 5.3.0以降では、config.jsが過去に行ったことを処理するmain.jsが導入されています。 変更は、公式移行ドキュメントに記載されています。

Storybook 5.3.0以降を使用している場合は、config.jsファイルは不要であり、この手順は無視してかまいません。

公式ドキュメントは、storiesを配置するためのさまざまなアプローチも提案しています。

この時点で、ストーリーブックが使用できるように設定されています。

ステップ2—Reactアプリにストーリーを追加する

セットアップが完了したので、Storybookを使用してコンポーネントを作成できます。

このチュートリアルでは、<Button>コンポーネントを作成し、このコンポーネントについては、storiesフォルダー内にそれらのストーリーを文書化します。 先に進み、componentディレクトリ内に次のコード行を使用して<Button>コンポーネントを作成します。

src / components / Button.js
import React from 'react';
import './Button.css';

const Button = props => (
  <button onClick={props.onClick} style={props.style}>
    {props.label && <span>{props.label}</span>}
  </button>
);

export default Button;

そして、コンポーネントのスタイルを追加します。

src / components / Button.css
button {
  padding: 20px;
  width: 20em;
  margin: 10px;
  color: white;
  font-size: 19px;
  cursor: pointer;
  border: 2px solid #fecd43;
  background: #fecd43;
}

これで、作成した<Button>コンポーネントのストーリーを追加できます。 storiesディレクトリ内にファイルを作成し、それをbuttonStories.jsと呼び、次のコード行をファイルに追加します。

src / stories / buttonStories.js
import React from 'react';
import { storiesOf } from '@storybook/react';

import Button from '../components/Button';

storiesOf('Button', module)
  .add('with primary', () => <Button label="Primary Button" />)
  .add('with outline', () => <Button
    label="Ouline Button"
    style={{ background: 'transparent', border: '3px solid #fecd43' }}
  />)
  .add('with rounder corners', () => <Button
    label="Rounded Button"
    style={{ borderRadius: '15px' }}
  />)
  .add('disabled', () => <Button disabled
    label="Disabled Button"
    style={{ background: 'gray' , border: 'gray', cursor: 'not-allowed' }}
  />);

次に、index.jsファイルを作成します。 buttonStories.jsファイルをインポートします。

src / stories / index.js
import './buttonStories';

これはすべてのストーリーを含むベースファイルとして機能し、すべてをこのファイルにインポートできます。

注: Storybook 5.3.0以降では、*.stories.jsのファイル名パターンが採用されています。 この規則に合わせるには、buttonStories.jsの名前をbutton.stories.jsに変更する必要があります。

同じButtonタイトルを使用するデモストーリー用に生成された1-Button.stories.jsファイルに遭遇することもあります。 混乱を避けるために、そのファイルの内容をコメントアウトすることができます。

次に、storiesディレクトリの下に作成された新しいファイルごとに、それらをこのファイルにインポートします。

ステップ3—アドオンの統合

Storybookを備えたアドオンは、追加機能を実装して、それらをより便利でインタラクティブにするのに役立ちます。 Storybookで利用可能なすべてのアドオンの完全なリストは、公式サイトにあります。

この記事では、作成したストーリーにActionアドオンを追加します。 アクションアドオンを使用して、ストーリーブックのイベントハンドラーが受信したデータを表示できます。

アドオンを手動で追加する

アドオンがデフォルトでまだ設定されていない場合は、次の手順に従う必要があります。

注: Storybook 5.3.0以降を使用している場合、このチュートリアルでは、addons.jsファイルは必要ないため、この手順は無視してかまいません。

次のコマンドでアドオンパッケージをインストールします。

  1. npm install --save-dev @storybook/addon-actions

次に、次のコンテンツを.storybook/addons.jsに追加します。

.storybook / addons.js
import '@storybook/addon-actions/register';

これで、ストーリーブックはアドオンをサポートします。

ステップ4—アドオンアクションの使用

ButtonストーリーをStorybookとインタラクティブにするために、次のコードをbuttonStories.jsに追加できます。

src / stories / buttonStories.js
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';

import Button from '../components/Button';

storiesOf('Button', module)
  .add('with primary', () => <Button
    onClick={action('click')}
    label="Primary Button"
  />)
  .add('with outline', () => <Button
    label="Ouline Button"
    onClick={action('click')}
    style={{ background: 'transparent', border: '3px solid #fecd43' }}
  />)
  .add('with rounder corners', () => <Button
    label="Rounded Button"
    onClick={action('click')}
    style={{ borderRadius: '15px' }}
  />)
  .add('disabled', () => <Button disabled
    label="Disabled Button"
    onClick={action('click')}
    style={{ background: 'gray' , border: 'gray', cursor: 'not-allowed' }}
  />);

次に、ストーリーブックを実行します。

Animated gif of Storybook interface displaying the component and Actions tab.

下のタブでは、Actions tabが表示され、ボタンを操作するたびにアクションがログに記録されます。

ステップ5—テーマのカスタマイズ

Storybookでは、使用されるデフォルトのテーマをカスタマイズすることができ、Storybookにはデフォルトのライトテーマがバンドルされています。 それでは、これを別の何かにカスタマイズする方法を見てみましょう。 ダークテーマかもしれませんし、まったく違うものかもしれません。 開始するには、次のコード行を追加して、config.jsファイルで設定した構成を変更する必要があります。

.storybook / config.js
import { addParameters } from '@storybook/react';
import { themes } from '@storybook/theming';

addParameters({
  options: {
    theme: themes.dark
  }
});

Screenshot of the Storybook interface with dark theme.

注: Storybook 5.3.0以降では、manager.jsが導入されています。 この新しい規則でテーマを設定する手順は、公式のテーマ作成ドキュメントで説明されています。

ダークテーマを設定すると、ストーリーブックのテーマ全体がダークテーマに切り替わったことがわかります。 いつでも、好みに応じて、これを明るいテーマまたは暗いテーマに戻すことができます。

まったく別のテーマが必要な場合は、すぐに動的テーマを定義することもできます。 最初のステップは、テーマのファイルを作成することです。.storybookフォルダー内に、yourTheme.jsという名前の新しいファイルを作成します。 次のステップは、storybook/themingcreate()関数を使用して新しいテーマを生成することです。

pink.jsテーマの例を次に示します。

.storybook / pink.js
import { create } from '@storybook/theming';

export default create ({
  base: 'light',
  colorPrimary: 'hotpink',
  colorSecondary: 'deepskyblue',
  // UI
  appBg: 'rgb(234, 0, 133)',
  appContentBg: 'white',
  appBorderColor: 'white',
  appBorderRadius: 4,
  // Typography
  fontBase: '"Open Sans", sans-serif',
  fontCode: 'monospace',
  // Text colors
  textColor: 'rgb(255, 250, 250)',
  textInverseColor: 'white',
  // Toolbar default and active colors
  barTextColor: 'white',
  barSelectedColor: 'white',
  barBg: 'rgb(246, 153, 190)',
  // Form colors
  inputBg: 'white',
  inputBorder: 'silver',
  inputTextColor: 'black',
  inputBorderRadius: 4,
  brandTitle: 'Pink Storybook'
});

次に、Storybook構成ファイルにpink.jsをインポートします。

.storybook / config.js
import pink from './pink';

addParameters({
  options: {
    theme: pink
  }
});

Screenshot of the Storybook interface with the custom theme.

これにより、前の画像とはまったく異なるテーマが得られます。

ステップ6—ストーリーブックの展開

Storybookにバンドルされている機能の1つは、Storybookを静的サイトとして展開し、選択した任意のホスティングオプションに展開できることです。 これを構成するには、build-storybookスクリプトをpackage.jsonに追加する必要があります。

package.json
{
  "scripts": {
    "build-storybook": "build-storybook -c .storybook -o .out"
  }
}

このスクリプトは、ストーリーブックディレクトリを静的Webアプリに構築し、.outディレクトリに出力します。 このスクリプトを実行して、ビルドが完了したら.outディレクトリのコンテンツを展開できます。 先に進み、コマンドを実行します。

  1. npm run build-storybook

ビルドが完了すると、任意のホスティングを使用してディレクトリのコンテンツをデプロイできるようになります。

これがローカルで機能することをテストするには、次のコマンドを実行できます。

  1. npx http-server .out

注: package.jsonには、build-storybook -s publicに似たbuild-storybookスクリプトが含まれている場合があります。 指定された.outディレクトリではなく、静的サイトファイルをstorybook-staticディレクトリに出力します。

これにより、フォルダーのコンテンツが静的サイトとして提供されます。

結論

この記事では、StorybookとReactを使用してインタラクティブなコンポーネントを構築する方法を学びました。 これで、Storybookで何が可能かを探り、StorybookをコンポーネントライブラリとしてReactプロジェクトに統合する方法についてのガイドもあります。 Storybookを使用した開発は、チームで作業する開発者と設計者の両方にとって信頼できる唯一の情報源として機能し、他のフロントエンドフレームワークと統合できます。

この投稿では、Reactでの使用方法についてのみ概説しています。 他のフレームワークのガイドをお探しの場合は、Storybookの公式ドキュメントをお気軽に確認してください。

この記事のコードはGitHubにもあります。