こんにちは。ISID コミュニケーションIT事業部 瀧川亮弘(あきひろ)です。
プロジェクトにてStorybook
を利用しています。
Storybook
の概要と基本的な実装方法をお伝えできればと思います。
Storybookとは?
一言でいうとUIのカタログです。また、それを作成するためのライブラリです。
Storybook
を利用することで、GUI上でUIコンポーネントのデザインや振る舞いを簡単に確認できます。
百聞は一見にしかずということで、普段大変お世話になっているVSCode
のStorybook
のリンクを貼っておきます。良かったら触ってみてください!
Microsoft VSCode Webview UI Toolkit
Storybookの実装
UIコンポーネントをStorybook
上で表示するために.stories.js
という拡張子のファイルを作成する必要があります。
本章では、こちらのファイルの基本的な実装について記載します。
尚、いくつか存在する記法のうち、CSF(Component Story Format)
という記法を採用します。以前まで主流だった、storiesOf
関数やadd
関数を利用するstoriesOf API
は現在非推奨となっています。
余談ですが、筆者はstoriesOf API
で記載された数十のファイルをCSF
に書き換える作業をしたことがあります。個々の作業は簡単でしたが、数が数だけにとても苦労した懐かしい思い出があります。
対象のコンポーネント
対象とするコンポーネントとして、簡単なボタンを用意しました。
愛着が湧くように自身の名前をつけてAkiButton
と名付けました。
Vue3
のscript setup
構文を利用しています。
<template> <button class="button" :class="[getColor]" @click="handleClick"> <slot /> </button> </template> <script setup lang="ts"> import { computed } from "vue"; interface Props { /** * 色 */ color?: "basic" | "primary" | "error"; } const props = withDefaults(defineProps<Props>(), { color: "basic", }); interface Emits { /** * クリックイベント */ (e: "click"): void; } const emit = defineEmits<Emits>(); const handleClick = () => { emit("click"); }; const getColor = computed<string>(() => `button__color--${props.color}`); </script> <style lang="scss" scoped> .button { height: 30px; padding: 0 16px; cursor: pointer; &__color { &--basic { background-color: $color__primary-light; border-color: $color__primary-light; color: $color__primary; } &--primary { background-color: $color__primary; border-color: $color__primary; color: $color__white; } &--error { background-color: $color__error; border-color: $color__error; color: $color__white; } } } </style>
実装
完成形
まずは完成形をお見せします。
次章から順を追って実装を確認します。
import AkiButton from "./AkiButton.vue"; export default { title: "Atoms/AkiButton", component: AkiButton, argTypes: { color: { control: { type: "select", options: ["basic", "primary", "error"], }, }, click: { action: "click", }, }, }; const Template = (args, { argTypes }) => ({ components: { AkiButton }, setup() { return { ...args, }; }, template: ` <AkiButton :color="color" @click="click">あきボタン</AkiButton> `, }); export const Basic = Template.bind({}); Basic.args = { color: "basic", }; export const Primary = Template.bind({}); Primary.args = { color: "primary", }; export const Error = Template.bind({}); Error.args = { color: "error", };
メタデータの定義
メタデータを定義します。
title
には、メニューに表示される名前を定義します。/(スラッシュ)
で階層を切ると、GUI上ツリー表示されます。ちなみに、現在のプロジェクトではAtomic Design
に基づいて階層を切っています。
component
には、対象のコンポーネントで用意したコンポーネントを指定しています。
これらを指定したオブジェクトをデフォルトエクスポートすることでメタデータとして認識してくれます。
import AkiButton from "./AkiButton.vue"; export default { title: "Atoms/AkiButton", component: AkiButton, };
テンプレートの定義
テンプレートを定義します。
次章でいくつかのストーリーを定義しますが、それらのストーリーが共通して利用するテンプレートとなります。各ストーリーで利用する関数なので、テンプレート自体のexport
は必要ありません。
テンプレートの関数は、引数として各ストーリーごとに定義されたプロパティを受け取ります。ここではargs
という名前で受け取ったプロパティを対象コンポーネントに渡しています。
const Template = (args, { argTypes }) => ({ components: { AkiButton }, setup() { return { ...args, }; }, template: ` <AkiButton :color="color" @click="click">あきボタン</AkiButton> `, });
ストーリーの定義
Storybook
のメインであるストーリーを定義します。
コンポーネントを表示するパターン、テストするパターンなどを考慮してストーリーを表現します。ここでは、color
プロパティの値ごとに、ストーリーを作成しています。
テンプレートの定義で用意したテンプレートの関数をもとにいくつかのストーリーを作成するのが便利です。
ストーリーは関数で表現し、名前付きエクスポートします。
ここでつけた名前がデフォルトではストーリー名となります。
export const Basic = Template.bind({}); Basic.args = { color: "basic", }; export const Primary = Template.bind({}); Primary.args = { color: "primary", }; export const Error = Template.bind({}); Error.args = { color: "error", };
アドオンを利用する
アドオンとはStorybookの拡張モジュールのことです。
今回はStorybookが公式でサポートしている3つのアドオンを利用してみます。
Controlsアドオン
Controls
アドオンにより、コンポーネントに対するプロパティをGUI上で動的に切り替えることができます。
argTypes: { color: { control: { type: "select", options: ["basic", "primary", "error"], }, }, },
Actionsアドオン
Actions
アドオンにより、発火されたイベントをロギングします。
各イベントが発火するタイミングやイベントの内容を確認できます。
argTypes: { click: { action: "click", }, },
Docsアドオン
Docs
アドオンは、ソースコードを解析しドキュメントを自動生成してくれます。
Vueファイルに記載したコメントがドキュメントに反映されていることがわかります。
/** * 色 */ color?: "basic" | "primary" | "error";
storybook
実装方法は以上です。
必要に応じて、アドオンを追加するとよいでしょう。
SDD(Storybook Driven Development)のすゝめ
Storybookとは?ではStorybook
をUIカタログとご紹介しましたが、Storybook
をUIの開発環境と捉えることもできます。
UIコンポーネントをアプリケーションから切り離された環境(Storybook
上)で開発することには以下のようなメリットがあると思います。
- UIコンポーネントの粒度や責務を適切に保つことができる
- 開発者が並行して作業を進めやすい
皆さんもよければ、Storybook
上で開発してみてください。
最後に
いかがでしたか?
Storybook
って面白いなと思っていただけたら嬉しいです!
では、よいStorybook
生活を!
執筆:@takigawa.akihiro、レビュー:@shibata.takao (Shodoで執筆されました)