Help us understand the problem. What is going on with this article?

Storybookの新しいアドオン addon-docs がいい感じ

More than 1 year has passed since last update.

Storybookのv5.2 で入る予定の新しいアドオン addon-docs を試してみたら、なかなかいい感じだったので布教記事を書きます。

image.png

実物はGitHub Pagesで公開しています。
https://y-takey.github.io/storybook_docs_example/
(リポジトリ: https://github.com/y-takey/storybook_docs_example )

addon-docs は (既存のアドオンである) addon-info をほぼ置き換える新しいアドオンで、従来のストーリー形式に加えて MDXも使えることが一番の特徴だと思います。上の画像のようなドキュメントを手軽に書くことができます。
MDXを使えることが理由で、 StyleguidistDocz を選んだ人もいるんじゃないかと思いますが、これからは Storybook も負けていません。


※ 本記事は Storybook および addon-docs のバージョン 5.2.0-alpha.29 を元にしており、最新バージョンでは設定や使用方法が変わっている可能性がありますのでご注意下さい。

設定方法など

Storybook自体のインストール・設定は終わっている前提で、addon-docs のインストール・設定等は次のとおりです。

Storybook 本体と既存アドオンのアップグレード

2019/06/23 時点では Storybook@5.2 はまだ正式リリースされていないため、debug を指定してアップグレードします。

yarn upgrade @storybook/react@debug @storybook/addons@debug @storybook/addon-actions@debug

他にも使用している公式アドオンがあれば同様にアップグレードしてください。

addon-docs 等のインストール

yarn add -D @storybook/addon-docs@debug @storybook/source-loader@debug

addon-docs の他に、ソースも表示できるようにするために @storybook/source-loader もインストールしています。
ソース表示が不要な場合はインストールしなくても大丈夫です。

addon-docs の設定など

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

load(require.context('../src', true, /\.stories\.[tj]sx?$/), module);
load(require.context('../src', true, /\.stories\.mdx$/), module);

ロード対象ファイルの正規表現は適宜変えて下さい。この例では TypeScript , mdx をロードするようにしています。
今回はMDXのみとするので書いていませんが、以下の設定を上の config.js に追加すると、従来のストーリにも自動で(ある程度よしなに)ドキュメントを追加してくれます。

.storybook/config.js
import { addParameters } from '@storybook/react'
import { DocsPage } from '@storybook/addon-docs/blocks';

addParameters({
  docs: DocsPage,
});
.storybook/presets.js
module.exports = [
  '@storybook/addon-docs/react/preset',
];
.storybook/webpack.config
const path = require('path');

module.exports = ({ config }) => {
  config.module.rules.push({
    test: /\.stories\.[tj]sx?$/,
    use: [
      {
        loader: require.resolve('@storybook/source-loader'),
        options: { injectParameters: true },
      },
    ],
    include: [path.resolve(__dirname, '../src')],
    enforce: 'pre',
  }, {
    test: /\.(ts|tsx)$/,
    use: [
      {
        loader: require.resolve('awesome-typescript-loader'),
      },
      {
        loader: require.resolve('react-docgen-typescript-loader'),
      },
    ],
    include: [path.resolve(__dirname, '../src')],
  });
  config.resolve.extensions.push('.ts', '.tsx');

  return config;
};

ソースコードを表示するには @storybook/source-loader が必要となるため、 webpack.config に設定を追加します。(module.rules.push の1つ目の引数)
また TypeScript のソースコードから props のテーブルを表示するには react-docgen-typescript-loader が必要となるため、こちらもwebpack.config に設定を追加します。(module.rules.push の2つ目の引数)
ここでは awesome-typescript-loader を使っていますが、 ts-loader でも大丈夫です。ちなみに、TypeScriptまわりの設定については、 @storybook/preset-typescript を使えばwebpackの設定を自分でやる必要はありません。(内部では ts-loader, react-docgen-typescript-loader を追加してくます)

また、TypeScriptの他にも prop-types, flowでも props のテーブルを表示してくれます。(それぞれの対応する loader の設定が必要)

MDX

ドキュメントは以下のような感じで書きます。(MDXのハイライトがないみたいで、ちょっと見にくいかもしれません。)

Button.stories.mdx
import { action } from "@storybook/addon-actions";
import { Story, Meta, Preview, Props, Source, Description } from "@storybook/addon-docs/blocks";

import Button from "./Button";

<Meta title="hoge" parameters={{ component: Button }} />

# Button

何の変哲もないただのボタン

<Source code={`import Button from "~/components/Button";`} />

<Preview withSource="open">
  <Story name="basic" >
    <Button label="this is src" onClick={action('clicked')} />
  </Story>
</Preview>

<Props of="." />

@storybook/addon-docs/blocks から import できるコンポーネントは以下のものがあります。

Meta

Props

プロパティ 必須 説明
title 必須 サイドバーに表示されるタイトル。"¦"(縦棒)でセクショニングできて、"/"で階層化できる。(たぶん addon-info と同じ記法)
decorators 任意(デフォはなし) addon-info と同様なため詳細はそちらを参照。指定する場合は1つでもdecoratorの配列にする必要がある。
parameters 任意(デフォはなし) { component, notes, info } のオブジェクトでいずれも任意要素。後述の Props, Description 等のコンポーネントから参照される。

<Meta
  title="セクションA|Components/Button"
  parameters={{
    component: Button,
    notes: "This is notes;",
    info: "This is info.",
  }}
/>

Preview

Props

プロパティ 必須 説明
withSource 任意(デフォは"closed") ソースも一緒に表示するかの設定で、"open"

<Preview withSource="open">
  <Story name="basic" >
    <Button label="this is src" onClick={action('clicked')} />
  </Story>
</Preview>

image.png

Story

Props

プロパティ 必須 説明
id 任意 他の箇所でidを指定して参照できるようになる。
name 任意 サイドメニューに表示される名称
height 任意 表示領域の高さ

<Story name="basic" >
  <Button label="this is src" onClick={action('clicked')} />
</Story>

Source

Props

プロパティ 必須 説明
code 必須 表示するソースコード
language 任意(デフォは"jsx") ハイライト用に使われる言語。

<Source code={`import Button from "~/components/Button";`} />

image.png

Props

Props

プロパティ 必須 説明
of 必須 対象のコンポーネント。"." でカレントコンポーネント(Metaコンポーネントの parameters.component )

<Props of={Button} />
// <Props of="." /> と書いても同じ

image.png

Description

Props

プロパティ 必須 説明
of 任意 対象のコンポーネント。"." でカレントコンポーネント。
markdown 任意 表示するマークダウンテキスト。
type 任意 "info", "notes", "docgen", "auto" のいずれかを指定可能。"info", "notes" は Meta コンポーネントの parameters プロパティで指定した 同名の要素を使用する。"docgen" は各種のdocgen loader によって注入される 対象コンポーネントの __docgenInfo.description を使用する。

markdown が指定されている場合には type は無視される。

<Description markdown="**BOLD**" />

<Description type="info" />

image.png

その他

Storybook は React 以外にも Vue や Angular 等など色々サポートしていますが、 addon-docs が対応しているのは現時点では React, Vue だけです。( Vue は一部未実装の模様)
Angularも今後対応予定のようです。


説明は以上です。まだまだドキュメントがほとんどないため addon-docs のソースコードも読みながら調べた内容をまとめてみました。
正式リリースされる際にはきっとドキュメントも整備されていると思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away