Reactのライブラリを開発しているときに立ちはだかるのが、実際に開発中のものをインストールして動かしたりしないと確認できないということです。
ここでStorybookという、Previewにもってこいのライブラリがあったので、導入していきたいと思います。
あと、このStorybookはGithubPagesに公開することで、Repositoryから簡単にテストしてもらうことができるようになります。
Storybookの導入
とりあえず、プロジェクトにStorybookを導入します。
$ npx storybook init Need to install the following packages: storybook Ok to proceed? (y) y
npm8を使ってるプロジェクトだと、以下のような警告が出てくる場合があります。
We've detected you are running npm 8.11.0 which has peer dependency semantics which Storybook is incompatible with. In order to work with Storybook's package structure, you'll need to run `npm` with the `--legacy-peer-deps=true` flag. We can generate an `.npmrc` which will do that automatically. More info: https://github.com/storybookjs/storybook/issues/18298 Do you want to run the 'npm7' migration on your project?
どうもnpm8だと、依存関係の問題で正常に動作しないらしく、npm7のマイグレーションを行うことで使えるようになるようです。
特に問題がない人は、マイグレーションを実行します。そうすると .npmrc
というファイルが作成されます。
.npmrcとはなんぞや
npmを実行するときの設定値を書いておくためのファイルです。
.eslintrc.js
, prettierrc.js
とかと同じ感じですね。
インストールが終わると以下のようになるので npm run storybook
を実行します。
✔ Do you want to run the 'npm7' migration on your project? … yes ✅ ran npm7 migration ✅ migration check successfully ran To run your Storybook, type: npm run storybook For more information visit: https://storybook.js.org
storybookを起動すると、ブラウザが自動的に立ち上がって色々と作業ができるようになります。
Storyboardの書き方
インストールしたてのStoryboard画面。ここにいくつかカスタマイズと、実際にコンポーネントを表示できるようにしていきます。
cssを適用する
現状のままだと、Componentが左上に寄って表示されてしまうので、センタリングされるようにカスタムcssを適用できるようにします。
まずは.storybook/assets/css
にstyles.css
を作成して、以下をコピペします。
.preview-container { display: flex; justify-content: center; align-content: center; height: stretch; } .content-container { align-self: center; padding: 10px; } .content-container::-webkit-scrollbar { display: none; }
次に styles.css
を読み込めるように .storybook/preview.js
に以下の項目を追加します。
+ import "./assets/css/styles.css"; + export const parameters = { actions: { argTypesRegex: "^on[A-Z].*" }, controls: { matchers: { color: /(background|color)$/i, date: /Date$/, }, }, }
CLIでstorybookを起動している場合は再起動してから、ブラウザのDevTools等で確認すると、読み込まれていることが分かります。
background-colorを変更できるようにする
初期値では light
, dark
の2つしか選択できないので、もう少し選択できるように種類を増やします。
.storybook/
にbackgrounds.js
というファイルを作成し、以下の内容をコピペします。
もっと色を増やしたい場合には、同じようなフォーマットでパターンを追加します。
const backgrounds = { default: 'White', values: [ {name: 'White', value: '#FFFFFF', default: true}, {name: 'Whitesmoke', value: 'whitesmoke'}, {name: 'Black', value: 'black'}, {name: 'Red', value: '#EF9A9A'}, {name: 'Pink', value: '#F48FB1'}, {name: 'Purple', value: '#CE93D8'}, {name: 'Deep Purple', value: '#B39DDB'}, {name: 'Indigo', value: '#9FA8DA'}, {name: 'Blue', value: '#90CAF9'}, {name: 'Light Blue', value: '#81D4FA'}, {name: 'Dark Blue', value: '#5CB1EC'}, {name: 'Green', value: '#A5D6A7'}, {name: 'Deep Orange', value: '#FFAB91'}, {name: 'Blue Grey', value: '#B0BEC5'} ] }; export default backgrounds;
preview画面で設定できるように、.storybook/preview.js
に以下の行を追加します。
import "./assets/css/styles.css"; + import backgrounds from "./backgrounds"; export const parameters = { actions: { argTypesRegex: "^on[A-Z].*" }, + backgrounds, controls: { matchers: { color: /(background|color)$/i, date: /Date$/, }, }, }
設定が終わると、設定できるbackgroundColorが増えていると思います。
storiesファイルを作る
storybookをインストールすると stories
というフォルダが作成されますが、
個人的には、componentsと同じ箇所にある方が、メンテナンスしやすいかなと思いそうしていますが、ここは各自の方針で実装してください。
細かい書き方については、実際にstorybookを導入しているライブラリがありますので、確認してみてください。
まずは、storybookに表示するメタ情報をexport default
で定義します。
export default { title: "Timeline Embed Components", component: TwitterTimelineEmbed, argTypes: { backgroundColor: { control: "color" } } } as ComponentMeta<typeof TimelineEmbed>;
次に、Previewしたいコンポーネントのベース定義をします。
ここでのargs
とは、このテンプレートを継承した各パターン定義の際に設定するargs
が代入されてきます。
const Template: Story<TimelineEmbedProps> = (args) => ( <div className="preview-container"> <div className="content-container"> <TimelineEmbed {...args} /> </div> </div> );
定義したテンプレートを継承した、各プレビューパターンを定義します。
export const TimelineFromScreenName = Template.bind({}); TimelineFromScreenName.args = { sourceType: "profile", screenName: "nomunomu0504", options: { width: 400, }, }; export const TimelineFromUserId = Template.bind({}); TimelineFromUserId.args = { sourceType: "profile", userId: "740893939977195520", options: { width: 400, }, };
最終的には、こんな感じになります。
import { Story, ComponentMeta } from "@storybook/react"; import { TimelineEmbed } from "../TimelineEmbed"; import { TimelineEmbedProps } from "../types/TimelineEmbed"; export default { title: "Timeline Embed Components", component: TimelineEmbed, argTypes: { backgroundColor: { control: "color", }, }, } as ComponentMeta<typeof TimelineEmbed>; const Template: Story<TimelineEmbedProps> = (args) => ( <div className="preview-container"> <div className="content-container"> <TimelineEmbed {...args} /> </div> </div> ); export const TimelineFromScreenName = Template.bind({}); TimelineFromScreenName.args = { sourceType: "profile", screenName: "nomunomu0504", options: { width: 400, }, }; export const TimelineFromUserId = Template.bind({}); TimelineFromUserId.args = { sourceType: "profile", userId: "740893939977195520", options: { width: 400, }, };
ここまで実装して、storybook-cliを再起動すると、ブラウザでコンポーネントが確認できるようになっています。
コンポーネントへ受け渡すための引数に対して、JSDoc等でコメントを記載しておくと、Docsタブを開いた際に自動的に説明文として設定することができます。
export type TimelineProfileDataSource = | { sourceType: "profile"; /** * Valid Twitter username */ screenName: string; /** * Additional options */ options?: CommonOption & TimelineEmbedOption; } | { sourceType: "profile"; /** * Valid Twitter user ID */ userId: stirng; /** * Additional options */ options?: CommonOption & TimelineEmbedOption; };
このstoriesファイルを、全てのコンポーネントに対して作成することで、手軽にコンポーネントをテストすることができるようになります。