yonemoto

Vue CLI と Storybookでスタイルガイドを作成しよう

サイトの規模やスケジュールに応じてスタイルガイドを作成した方が効率良く進められるケースもあるかと思います。スタイルガイドを作成するメリットにはデザインの統一、テストや運用の効率化などが挙げられます。
とくにスタイルガイドを用いてプロジェクトに関わるメンバー(ディレクター、エンジニア、デザイナー)間の認識を共通化することはプロジェクト進行において非常に重要な意味を持ちます。

スタイルガイドとは、デザインする前の要素やグラフィック、デザイナーやエンジニアが従うべきルールなどを集めたものです。スタイルガイドがあれば、バラバラのWebサイトの部品に一貫性を持たせて、最終的に一体感のある体験を作り出すことができます。

引用:Webデザインのスタイルガイドの作り方

ただし、スタイルガイド導入にはメリット、デメリットがあります。導入するべきプロジェクトなのかは見極めが必要になります。
質の高いスタイルガイドを作成するために考えておくべきこと

スタイルガイドの作成にはスタイルガイドジェネレーターを利用することが一般的です。スタイルガイドジェネレーターにはさまざまなツールの選択肢があります。この記事では最近注目を集めるReact, Vue.js, AngularといったライブラリをサポートするStorybookを用いた方法を紹介したいと思います。

StorybookはUIコンポーネント開発環境を提供するオープンソースツールです。コンポーネントを一覧にしてカタログ化したり、各コンポーネントの見た目や振る舞いを容易にテスト、管理できることが特徴です。

それでは手を動かしながら導入方法を見ていきましょう。
まずはVue CLIを利用できる環境を用意します。Vue CLIはVue.jsを用いた開発環境一式を整えてくれる公式のコマンドラインツールです。

Vue CLIのインストール

以下のコマンドでVue CLIをグローバルにインストールします。npm, Yarnどちらでもインストール可能ですが、Yarnの場合は一度インストールしたパッケージはキャッシュされるので再インストールが高速化されます。
Yarn公式サイト

# npmを利用した場合
npm install -g @vue/cli

# Yarnを利用した場合
yarn global add @vue/cli

次のコマンドでバージョンが表示されればOKです。

vue --version

vue createコマンドで新規プロジェクトを作成してみましょう。ここではプロジェクト名をstyle-guideとしてみます。

vue create style-guide

実行すると以下のような画面が表示されます。Vue CLIではこのように対話形式でフロントエンド開発に必要な環境を簡単に準備できます。defaultではBabelとESLintの利用環境が標準でセットアップされます。Manually select featuresにすると手動で必要な環境を選択することが可能です。

手動選択にすると以下のような対話が始まります。ここでの設定は必要に応じて自由にセットアップしてください。

今回はdefaultを選択して進めてみます。
ひととおりセットアップが完了したら、以下のコマンドを実行してブラウザでの表示を確認してみましょう。

cd style-guide
yarn serve --open

ローカルサーバーが立ち上がり、次のような画面が表示されれば完了です。

Storybookの導入

これでStorybookを導入する下準備が整いました。
Storybookの導入方法には手動で行う方法などいくつかありますが、今回は自動でStorybookのセットアップできる方法を紹介します。
Storybook for Vue

先ほど作成したプロジェクトのディレクトリーへ移動し、以下のコマンドでStorybookをインストールします。

npx -p @storybook/cli sb init --type vue

package.jsonを開いてみるとscriptsやdevDependenciesにStorybookの記述がされているのが分かります。

"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "storybook": "start-storybook -p 6006",
    "build-storybook": "build-storybook"
  }

まずは以下のコマンドでStorybookを起動させてみましょう。

yarn storybook

Storybookを起動させるとローカルで開発サーバーが立ち上がります。
Storybookの画面は主に3つのパネルに分けることができます。左サイドバーには作成したストーリー(コンポーネント)の一覧が表示されます。右側の画面上部には各コンポーネントのプレビューが表示されます。右の画面下部ではStorybookのアドオンにより拡張される画面となります。

単一ファイルコンポーネント

試しに簡易的なテキスト入力フォームのコンポーネントを作ってみたいと思います。
まずはsrcディレクトリー直下のcomponentsフォルダーにTextArea.vueファイルを作成します。ファイルの記述は以下のコードをコピペしてご利用ください。

以下ようなコンポーネントファイルの構成を単一ファイルコンポーネントと呼びます。
SFC(Single File Components)と呼ばれることもあります。
単一ファイルコンポーネントは3つのブロック(template、script、style)に分けられます。

templateタグ内にはHTMLが入ります。標準のマークアップ言語はHTMLになりますがPugなどのメタ言語を利用できるように設定することもできます。
scriptタグ内にはコンポーネントの振る舞いがJavaScriptで記述されます。
styleタグの中にはコンポーネントの見た目を制御するCSSが記述されます。CSSもHTMLの場合と同じくメタ言語のSassが利用できるように設定できます。

CSSはグローバルスコープなので、スタイルの干渉が起きないようにBEMなどの命名規則を用いたり、FLOCSSやECSSといったCSS設計を用いることが一般的です。
ですが、単一ファイルコンポーネントではstyleタグにscoped属性を付与することでコンポーネント単位のスタイルカプセル化が可能となります。

<template>
  <div class="text_area">
    <label class="text_area_label" for="message">{{ label }} <span class="text_area_required">必須</span></label>
    <textarea name="message" id="message" class="text_area_message" rows="10" v-model="text" v-on:keyup="validate"></textarea>
    <p class="text_area_confirm">入力内容: {{ text }}</p>
    <p class="text_area_alert" v-show="alert">*要望を入力してください</p>
  </div>
</template>

<script>
export default {
  name: 'TextArea',
  data() {
    return {
      label: 'お問い合わせ内容',
      text: '',
      alert: false
    }
  },
  methods: {
    validate: function () {
      if (this.text == '') {
       this.alert = true
      } else {
       this.alert = false 
      }
    }
  }
}
</script>

<style scoped>
.text_area_label {
  display: block;
  font-size: 1rem;
  margin-bottom: .6rem;
}
.text_area_required {
  background: red;
  color: #fff;
  font-size: .7rem;
  padding: .3rem .4rem;
  margin: 0 0 0 .4rem;
  display: inline-block;
  vertical-align: middle;
  line-height: 1;
}
.text_area_message {
  max-width: 640px;
  width: 100%;
}
.text_area_confirm {
  font-size: .8rem;
}
.text_area_alert {
  color: red;
}
</style>

ストーリーの実装方法

コンポーネントの用意ができたら試しにApp.vueファイルで読み込んでみます。TextArea.vueをimportしてTextAreaとして読み込んでいます。
template、script箇所を全て差し替えてみてください。ちなみにVue.jsのコンポーネント名はパスカルケース(PascalCase)が推奨されています。
Vue.js公式サイト

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Welcome to Your Vue.js App"/>
    // TextAreaの出力を追記  
    <TextArea/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
// TextAreaの読み込みを追記
import TextArea from './components/TextArea.vue'

export default {
  name: 'app',
  components: {
    HelloWorld,
    // TextAreaの呼び出しを追記 
    TextArea
  }
}
</script>

以下のコマンドでローカルサーバーを起動し、TextArea.vueが読み込まれているか確認してみましょう。

yarn serve --open

今度はstories/index.stories.jsを開き、最後の行に以下のコードを追記します。

ここではFormというストーリー(コンポーネント)一覧にText Areaという名前で登録しました。

// TextArea.vueを読み込む
import TextArea from '../src/components/TextArea.vue'
// ストーリー(コンポーネント)の登録
storiesOf('Form', module).add('Text Area', () => ({
  components: { TextArea },
  template: '<TextArea/>',
}));

storybookを起動して登録された内容を確認してみます。

yarn storybook

Storybookの公開

作成したストーリー(コンポーネント)一覧をサーバーにアップして共有する場合もあるかと思います。そんな時にはbuild-storybookコマンドで静的ファイルとして書き出します。書き出されたファイルはstorybook-staticフォルダーにまとめられます。
storybook-staticフォルダーをサーバーにアップすることで共有が可能です。

デモ用スタイルガイド

まとめ

今回は割愛しましたがStorybookにはアドオンで機能を追加できます。
アドオンにはコンポーネント内のWEBアクセシビリティをチェックしてくれるaddon-a11yやコンポーネントのプロパティをGUIで変更できるようにするaddon-knobsなどがあります。必要に応じてインストールして使ってみてください。

新しいウェブ体験を作ろう TAMのPWA開発
お問い合わせはこちら