Edited at

VueでStorybookを使ってAtomicデザインで設計する


はじめに

VueでAtomicデザインに基づいてコンポーネントを設計する方法を記録に残しておきます。

今回はVue-cliの3系を用います。というのも最初Nuxtを使おうと思ったのですが、バージョン2系ではStorybook使えなくなっていたようです。

なのでStorybookを利用するする際にはVue-cliを使用しましよう。

テストも初めからセットでインストールでき、カスタマイズがしやすいです。SSRが必須要件でないのであればVue-cliを使用するのがおすすめです。


StorybookとAtomic Design

今回StorybookとAtomic Designに関する説明は省略します。

他のサイトで詳しく書いていただいている方がたくさんいるのでそちらを参照してください

Storybook

Storybook公式サイト

Storybookがなぜ必要か?(Vue.js編)

Atomic design

Atomic Design を分かったつもりになる


Vue-cli3でVueの環境構築

まずバージョン2系以前のVue-cliが残っている可能性がある場合には削除しておきましょう。

yarn global remove vue-cli

それでは3系をインストールしていきましょう。バーション2系とはインストールするものが違うので気をつけてください。

yarn global add @vue/cli

以下のコマンドを実行して3系がインストールされていれば問題ないです。

vue --version

次にプロジェクトを作成しましょう。

プロジェクトを作成したいディレクトリで以下のコマンドを実行します。

vue create sample-storybook-vue

設定はお好みでお願いします。ユニットテストやE2EやTypescriptで構築しています。

これでプロジェクトの作成が完了しました。


Storybookの環境を構築

プロジェクト内に入ったら以下のコマンドを実行します。

vue add storybook

これでStorybookの環境構築が完了です。一瞬ですね!

storybookのconfigファイルを少しいじります。

私の場合はCSSフレームワークにVuetify、Material Designを使用したかったので以下のような設定になっています。

シンプルな設定であればVue.useやaddDecoratorはいらないです。


config/storybook/config.js

import { configure, addDecorator } from "@storybook/vue";

import Vue from "vue";
import Vuetify from "vuetify";
import "vuetify/dist/vuetify.css";
import "material-design-icons-iconfont/dist/material-design-icons.css";

Vue.use(Vuetify, {
iconfont: "md"
});

addDecorator(() => ({
template: "<v-app><story/></v-app>"
}));

const req = require.context("../../src/stories", true, /.stories.js$/);

function loadStories() {
req.keys().forEach(filename => req(filename));
}

configure(loadStories, module);


これでStorybookを立ち上げる準備ができました。


コンポーネントの作成

続いて使用するcomponentを作成します。

Atomicデザインを用いてコンポーネントの設計をしているのでcomponentディレクトリ内にAtoms、Molecules、Organisms、Templatesのディレクトリを作成しましょう。

Atomicデザインを採用するチームだとデザイナーやコーダーが作成したHTMLとCSSを元にデザインを分割していくという方法もあります。

また自分の様に機能優先でデザインを後から調整する場合にはAtomsから作って後から組み上げていくということもあります。

これはプロジェクトによると思うので適宜着手する手順をを変えましょう。

それでは仮にButtonのコンポーネントを作成します。


Button.vue

<template>

<v-btn :color="color">
<slot></slot>
</v-btn>
</template>

<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";

@Component({
name: "Button"
})
export default class Button extends Vue {
@Prop() private color!: string;
}
</script>


もう一つフォームテキストのコンポーネントも作成しましょう。


FormText.vue

<template>

<v-text-field :label="label" :placeholder="placeholder"></v-text-field>
</template>

<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";

@Component({
name: "Text"
})
export default class FormText extends Vue {
@Prop() label!: string;
@Prop() placeholder!: string;
mounted() {
console.log("this.label", this.label);
}
}
</script>


これで2つAtomsのコンポーネントを作成しました。これをStorybookで見れるようにしましょう。


stories/Atoms.stories.js

import { storiesOf } from "@storybook/vue";

import Button from "../components/Atoms/Button.vue";
import FormText from "../components/Atoms/FormText.vue";
import Icon from "../components/Atoms/Icon.vue";

storiesOf("Atoms", module)
.add("Button", () => ({
components: { Button },
template: '<Button color="success">Hello Button</Button>'
}))
.add("FormText", () => ({
components: { FormText },
data() {
return {
props: { label: "label", placeholder: "placeholder" }
};
},
template: "<FormText v-bind='props' />"
}));


StoryにAtomというタイトル名をつけて各コンポーネントからimportして表示させます。

各コンポーネントに適切なコンポーネントを渡すようにしてください。

ちなみにv-bindでpropsを渡すとspreadして子コンポーネントへPropsを渡すことができます。

通常のVueと同じようにdataでpropsを返してあげるとその値をテンプレートで渡すこととができます。

これと同様にMolecules、Organisms、Templatesのファイルも作成します。


まとめ

今回はVueでStorybookを利用してAtomic Designの環境を構築してみました。

さらにStorybookに関してはAddonを利用することで機能を拡張することができます。

そちらもぜひ活用してみてください