Chapter 12

[発展編] Decorators を定義する

shingo.sasaki
shingo.sasaki
2020.11.03に更新

Decorators とは

Decorator(デコレータ) は、ストーリーを描画する際に、そのストーリーをラップした上位コンポーネントのことです。

これまで登場してきた Viewports addonBackground addon も、内部的には Decorators を用いて、画面サイズや背景色を書き換えたラッパー内で対象ストーリーを描画することで実現しています。

デコレータは、アドオンを開発する一部の開発者に限らず、ストーリーを描画する共通スタイルを定義したり、依存性を注入したりするなど、ちょっとした一工夫をしたい際にも気軽に扱うことができます。

Decorators は、 Viewports addonBackground addon で使用してきた parameters フィールドと同様に

  • グローバルなデコレータ
  • 個別のコンポーネントに対するデコレータ
  • 個別のストーリーに対するデコレータ

を定義することができます。

ここでは、グローバルな Decorators の定義の仕方を紹介し、以降の章ではそれを使った応用例を紹介します。

グローバルなデコレータを定義する

全てのストーリーに共通して適用するデコレータを定義する場合は、 .storybook/preview.js 内に、 decorators フィールドを追加します。

decorators と、複数形になっていることからもわかるように、ここには配列で複数のデコレータを指定することができます。デコレータが複数ある場合は、定義した順に適用され、ラッパーをラップしたコンポーネントの形になります。

以下では、全てのストーリーの背景色をグレーにし、paddingを設定して対象ストーリーを描画するデコレータを作成しています。

.storybook/preview.js
export const decorators = [
  (story, context) => ({
    template: `
      <div style="backgroundColor: gray; padding: 10px">
        <story />
      </div>
    `
  })
]

decorators には、ラッパーコンポーネントを生成するための関数を定義しますが、その第一引数に対象ストーリーのコンポーネント(story)が渡されるため、 <story /> の形でテンプレートに含めて上げる必要があります。

ここでは、 <story /> を、 <div style="backgroundColor: gray; padding: 10px"> でラップすることで、全てのストーリーに 10px の padding と背景色を設定しています。

これによって、以下のように対象ストーリーに限らず、常に余白と背景色が反映されるようになります。

また、第二引数の context には、描画するストーリーに関する様々なメタデータが含まれています。

これまでに登場した argTypsparameters ほか、次章で扱う globals なども含まれているため、メタデータを元に様々なラッパーを定義することができます。

例えば、以下のデコレータは、対象ストーリーに関する基本的な情報をストーリーとセットで描画します。

.storybook/preview.js
export const decorators = [
  (story, context) => ({
    template: `
      <div>
        <h1>${context.kind}</h1>
        <h2>args</h2>
        <p>${JSON.stringify(context.args)}</p>
        <h2>Reuslt</h2>
        <story />
      </div>
    `
  })
]