Storybookの書き方をstoriesOfからCSFに書き換える方法

Nuxt

Storybook5.2からCSFが推奨の書き方となった

Storybook 5.2からStorybook’s Component Story Format (CSF)が推奨の書き方となりました。

今後は、今までのstoriesOfから、このCSFの形式が推奨となります。

Storybook’s Component Story Format (CSF) is the recommended way to write stories since Storybook 5.2. Read the announcement to learn more about how it came to be.
In CSF, stories and component metadata are defined as ES Modules. Every component story file consists of a required default export and one or more named exports.
CSF is supported in all frameworks except React Native, where you should use the storiesOf API instead.

https://storybook.js.org/docs/formats/component-story-format/

今回は、このstoriesOfからCSFへの書き換えを行いましたので、備忘録として記載しておきたいと思います。

なぜCSFを利用するのか?

実際にCSFへ書き換える前に、なぜCSFが推奨とされているのかを確認しておきたいと思います。

以下Storybook公式ブログに記載がありました!


🏆 Why a new format?
Imagine if developing a component in Storybook automatically unlocked the ability to test it with Jest, import it in Sketch designs, paste it into InVision prototypes, and visually test it in Chromatic. What if your component library was universally accessible inside all your favorite tools?
In the last three years, components have risen to dominate the UI landscape. Everywhere you look there are new component-oriented tools for development, testing, design, and prototyping.


https://medium.com/storybookjs/component-story-format-66f4c32366df



💎 Simple. Writing stories is as easy as exporting ES6 functions from your story file in a clean, standard format you know and love.
🚚 Portable. Component stories are easily consumed anywhere ES6 modules live, including your favorite testing tools like Jest and Cypress.
🔥 Optimized. Component stories don’t need any libraries other than your components. And because they’re ES6 modules, they’re even tree-shakeable!
☝️ Declarative. The declarative syntax is isomorphic to higher-level formats like MDX, enabling clean, verifiable transformations.
👾 Future-proof. Component stories hide Storybook’s underlying API, giving maintainers flexibility to improve Storybook without breaking any contracts.


https://medium.com/storybookjs/component-story-format-66f4c32366df

上記にある通り、CSFには様々な利点がありますが、JestやCypressなどのテストツールを含め、ES6モジュールが存在する場所であれば簡単に連携可能である点があげられます。

従来のstoriesOf形式では、Storybookの書き方にロックインするため他ツールへ応用がしづらかったというのがあるようです。

基本的な書き換え方法

それでは実際に書き換えを行っていきます!

Storybookの設定を修正

まずStorybookの設定ファイル.storybook/config.jsを以下のように修正します!

.storybook/config.js

import { configure, addDecorator } from '@storybook/react';
import { withInfo } from '@storybook/addon-info';
import { withKnobs } from '@storybook/addon-knobs';
import requireContext from 'require-context.macro';
import { withA11y } from '@storybook/addon-a11y';

addDecorator(withInfo);
addDecorator(withKnobs);
addDecorator(withA11y);

const req = requireContext('../src/components', true, /.(story|stories).tsx$/);

configure(req, module);

Storybookの修正

次は実際にstoriesOfで書かれたStorybookをCSFへ書き換えていきます!

修正前のStorybook

こちらがstoriesOfの形式で書かれたStorybookになります!

src/components/Something.stories.tsx

import React from 'react';
import { storiesOf } from '@storybook/react';
import Something from './Something';

const props = {
  isSomething: false,
  somethings: []
};

storiesOf('Something', module).add('show Something', () => {
  return <Something {...props} />;
});

修正後のStorybook

こちらがCSFの形式に書き換えを行ったStorybookになります!

export defaultでストーリーに関する属性を定義して、named exportでStorybookを表します。

src/components/Something.stories.tsx

import React from 'react';
import Something from './Something';

const props = {
  isSomething: false,
  somethings: []
};

export default {
  title: 'Something'
}

export const showSomething = () => <Something {...props} />;

Default exportについて

The default export defines metadata about your component, including the component itself, its title (where it will show up in the navigation UI story hierarchy), decorators, and parameterstitle should be unique, i.e. not re-used across files.

https://storybook.js.org/docs/formats/component-story-format/#default-export

Named story exportsについて

With CSF, every named export in the file represents a story function by default.

https://storybook.js.org/docs/formats/component-story-format/#named-story-exports

Storybookの起動

Storybookの起動コマンドを打って、Storybookを起動しましょう!

$ yarn storybook

これで修整したStorybookがちゃんと表示されていればOKです!

decoratorsを使用しているStorybookをCSFにするとき

decoratorsを使用しているStorybookをCSFへ書き換える時の方法を紹介しておきます!

こちらの記事を参考にしました!

修正前のStorybook

こちらがstoriesOfの形式で書かれたStorybookになります!

import React from 'react';
import { MemoryRouter } from 'react-router';
import Something from './Something';

export default {
  title: 'Something',
  decorators: [
    (storyFn: any) => (
      <MemoryRouter initialEntries={['/', '/']}>{storyFn()}</MemoryRouter>
    )
  ]
};

export const showSomething = () => <Something />;

修正後のStorybook

こちらがCSFの形式に書き換えを行ったStorybookになります!

addDecoratorを使用することで書き換えることができました!

import React from 'react';
import { MemoryRouter } from 'react-router';
import { storiesOf } from '@storybook/react';
import Something from './Something';

storiesOf('Something', module)
  .addDecorator(story => (
    <MemoryRouter initialEntries={['/', '/']}>{story()}</MemoryRouter>
  ))
  .add('show Something', () => <Something />);

参考サイト

Component Story Format (CSF)

Component Story Format – Storybook – Medium

まとめ

今回は、Storybookの書き方をstoriesOfからCSFに書き換える方法について紹介しました!

既存のStorybookを全部書き換えたので面倒でしたが、常に新しい技術を追ってついていくことはとても大切ですね!

もしStorybookをCSFへ書き換える際は是非参考にしてください。

オススメの関連商品

Note一覧

コメント