LoginSignup
2
1

備忘録 storybook7系とvuetify3の連携方法

Last updated at Posted at 2023-12-13

この記事はTechCommit Advent Calendar 2023の13日目の記事です。

前置き

  • vueプロジェクトはすでに作成済みという前提で話を進めます
  • storybookはすでにインストール済み、初期設定済みという前提で話を進めます
  • 関係なさそうな箇所はほとんど省略しております。
  • この記事が100%正しいという保証はありません。「おかしいな?」と思ったら別サイトを見ることを推奨します。

環境

各バージョン

バージョン
vite 7.6.3
vue 3.3.4
vuetify 3.4.4
storybook 7.6.3

ディレクトリ構造

今回の説明に関係なさそうなやつは全て省略
./storybook
 ├ main.js
 ├ preview.js
 ├ StoryWrapper.vue
 └ withVeutifyTheme.decorator.js
./src
 ├ plugins
  ├ vuetify.js

1. vuetifyをインストール

npm i vuetify

2. srcフォルダの中にpluginフォルダを作り、その中にvutify.jsファイルを作る

目的

  • main.jsのコード量を減らすため
  • 1つのファイルに書いて置くことによって二度手間を防ぐ

(というか、storybook関係なしにvuetifyにしろ、vuexにしろ、routerにしろこのようにするのが主流らしい)

vuetify公式のコードをちょっとだけいじるだけでok

src/plugins/vuetify.js
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'

export default createVuetify({
  components,
  directives,
})

3. srcフォルダの中にあるvueのmain.jsを編集

目的
vueでvuetifyを使えるようにするため

src / main.js
import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'
+ import vuetify  from './plugins/vuetify'

- createApp(App).mount('#app')
+ createApp(App).use(vuetify).mount('#app')

4. ラッパーを作る

ここからstorybookの話になります。
目的
vuetifyはv-appタグで囲まないと正しく動かないので(公式でも言ってる)
storyのコンポーネントをv-appタグで囲む

.storybook/StoryWrapper.vue
<template>
  <v-app>
    <v-main><slot name="story"></slot></v-main>
  </v-app>
</template>

<style>
.v-application__wrap {
  min-height: auto !important;
  /* これをしないと大きな余白が作られる */
  /* !importantしないと設定が上書きされるもよう */
}
</style>

5. withVuetifyTheme.decorator.jsを作る

目的
ストーリーブックのストーリーコンポーネントにVuetifyのテーマを適用するため

./storybook/withVuetifyTheme.decorator.js
import { h } from 'vue';
import StoryWrapper from './StoryWrapper.vue';

export const withVuetifyTheme = (storyFn, context) => {
  const story = storyFn();

  return () => {
    return h(
      StoryWrapper,
      {}, 
      {
        story: () => h(story, { ...context.args }),
      }
    );
  };
};
何やってるかわからないのでchatgptに聞いてみた。

コピペすると色々崩れるからスクショで
スクリーンショット (7310).png

h()について知りたい人は以下のサイトもどうぞ

6. 仕上げにpreview.jsに今まで作ったパーツを全部つなげる

.storybook/preview.js
/** @type { import('@storybook/vue3').Preview } */
+ import { setup } from '@storybook/vue3';
+ import { withVuetifyTheme } from './withVeutifyTheme.decorator';
+ import vuetify from '@/plugins/vuetify'

+ setup((app) => {
+   app.use(vuetify)
+ });

const preview = {
  parameters: {
+   decorators : {withVuetifyTheme},
    actions: { argTypesRegex: "^on[A-Z].*" },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
};


export default preview;

これで連携ができたはずです!
お疲れ様でした!

別の書き方について

一部の方々は上記の書き方に対して
「あれ?デコレーターは以下のように書くんじゃないの?」という疑問を持っているかもしれません。

export const decorators = [withVuetifyTheme];

この書き方でも問題なく動きました。

chatgptに質問したところ
この書き方は古いバージョンの書き方らしいです。
Storybook 6.0以降では、previewオブジェクトを使うことが推奨されていて、このオブジェクトのparametersプロパティにdecoratorsを指定します。

どちらの書き方でも問題ないようです。

次の記事紹介

14日目はやっしさんによるLeetCodeでアルゴリズム力を鍛えよう!です。

駄文のコーナー(ここから先は編集後記みたいなものなので飛ばしても大丈夫です。)

以下のサイトを参考にに作業していました。

ただこのサイトのpreview.jsで以下のようなことが出てきたんです。

import { registerPlugins } from '../src/plugins';

setup((app) => {
  // Registers your app's plugins into Storybook
  registerPlugins(app);
});

registerPluginsってなに!?
../src/pluginsってなんのこと!?
ってなって。これらが分からず色々調べてました。

どうやら
srcフォルダの中pluginフォルダの中にindex.jsファイルを作成し、そのファイルの中に
registerPlugins関数を作成して、引数で渡されたVueのアプリケーションに対して、フォントやプラグインを適用するというやりかたがあるようです。

例えばとしてこんな感じ

import vuetify from './vuetify'
import pinia from './store'
import router from './router'

export function registerPlugins(app) {
    app.use(vuetify)
        .use(router)
        .use(pinia)
}

今まで私は、preview.jsにも、main.jsにもvuetifyの設定は直接書き込んでました。

あと、私が作ったvueプロジェクトは、
storybookになれるために
storybookの公式サイトのvueチュートリアル以外のアプリを作ってstorybookを連携させて、
その後にvuetifyとの連携の仕方を勉強するためにvuetifyを当てただけなので。routerpiniavuexも使わずvuetifyしか使わないので今回はregisterPluginsを使わない方法を取りました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1