storybook: Vue + Vuetify theme not working

Bug or support request summary

Calling Vue.use (Vuetify {theme: { primary: <color>, etc.}}) is not working - a component that tries to use that theme does not take on the color, for instance.

Please provide issue details here - What did you expect to happen? What happened instead?

Component should use theme color in rendering. It does not.

Steps to reproduce

  • Create a minimal project with Vue cli (2 or 3)
  • in the config, import Vue and Vuetify
  • add a Vue.use() line, specifying a theme
  • create a component (VBtn works), that uses a color in the theme (primary, for instance))
  • create a story to invoke the button.

VBtn doesn’t take on the color. (in my test app, it does when run from dev/serve)

Please specify which version of Storybook and optionally any affected addons that you’re running

Affected platforms

  • _If UI related, please indicate:
    • chrome 69.0.3497.100 (Official Build) (64-bit), MacOS High Sierra
  • _If dependency related, please include relevant version numbers
    • vue - latest version (2.5.17)
    • vuetify - latest version (1.2.5)

Screenshots / Screencast / Code Snippets (Optional)

Example component:

<template>
  <v-btn round
    color="primary">
    <slot></slot>
  </v-btn>
</template>

<script>
export default {
  name: "test-button",
}
</script>

App file invoking the component:

  <v-app>
    <v-layout column justify-center>
      <v-layout row justify-center align-center>
         <test-button @click="testBtnClicked">
           Click It
         </test-button>
      </v-layout>
    </v-layout>
  </v-app>

Vue/Vuetify setup in config.js:

import Vue from 'vue';
import 'vuetify/dist/vuetify.min.css';
import Vuetify from "vuetify";
import colors from 'vuetify/es5/util/colors';

Vue.use(Vuetify, {
  theme: {
    primary: colors.indigo.base,
    info: colors.blue.lighten2,
    accent: colors.green.lighten1,
    error: colors.red.darken2
  }
});

Story for the TestButton:

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

import TestButton from "./TestButton.vue";

storiesOf("TestButton", module)
  .add("default", () => ({
    template: '<test-button>Click Me</test-button>',
    components: {TestButton}
  }))

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 23 (3 by maintainers)

Most upvoted comments

I have the problem too.

After reading vuetify’s code, seems the generation of CSS, and injection of the theme is made in the VApp mixin app-theme located here.

So, I think the problem is not linked to storybook, but vuetify instead.

By wrapping the component I wish to test with a v-app, it’s ok.

So, for now, please try to add a decorator in your config.js like this :

import { configure, addDecorator } from '@storybook/vue';
import 'vuetify/dist/vuetify.css';

import Vue from 'vue';
import Vuetify from 'vuetify';

Vue.use(Vuetify, {
  theme: {
    // your colors
  },
});

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

...

Sounds ok for you ?

I think you just need add <v-app> tag inside Story.

I have the whole storybook + vuetify + vue cli working perfectly, including scoped css. I post my setup here for whoever needs some help. My setup include 5 files:

main.js This is the storybook config file (I set up here webpack options)

const path = require('path')

module.exports = {
  //stories: ['../src/**/*.stories.mdx', '../src/stories/**/*.stories.@(js|jsx|ts|tsx)'],
  stories: ['../stories/**/*.stories.js'],
  addons: ['@storybook/addon-links', '@storybook/addon-essentials'],

  webpackFinal: async (config, { configType }) => {

    config.module.rules = config.module.rules.filter(rule =>
      !rule.test.test('.scss')
    )

    config.module.rules.push({
      test: /\.sass$/,
      use: [
        'style-loader',
        'css-loader', {
          loader: 'sass-loader',
          options: {
            implementation: require('sass'),
            prependData: `@import '@/styles/variables.scss'`,
            sassOptions: {
              fiber: require('fibers'),
              indentedSyntax: true
            }
          }
        }],
    }, {
      test: /\.scss$/,
      use: [
        'style-loader',
        'css-loader', {
          loader: 'sass-loader',
          options: {
            implementation: require('sass'),
            prependData: `@import '@/styles/variables.scss';`,
            sassOptions: {
              fiber: require('fibers'),
            }
          }
        }],
    })

    config.module.rules.push({
      resolve: {
        alias: {
          '@': path.resolve(__dirname, '../src'),
          '~': path.resolve(__dirname, '../src'),
          '~@': path.resolve(__dirname, '../src'),
          stories: path.resolve(__dirname, '../stories'),
          '.storybook': path.resolve(__dirname, '../.storybook'),
          vue: 'vue/dist/vue.js',
          'vue$': 'vue/dist/vue.esm.js',
        }
      }
    })
    return config
  }
}

preview.js This is the storybook file where I define the vuetify decorator.

import vuetifyConfig from './vuetify_storybook'
require('./vuetify_style.scss')

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  layout: 'centered',
  backgrounds: {
    default: 'light',
    values: [
      {
        name: 'dark',
        value: '#323539'
      },
      {
        name: 'light',
        value: '#F7F7F7'
      }
    ]
  }
}

export const decorators = [
  () => ({
    vuetify: vuetifyConfig,
    template: `
        <v-app style="background-color: transparent;" class="storybook">
          <v-main>
            <v-container fluid>
              <story />
            </v-container>
          </v-main>
        </v-app>
      `
  })
]

preview-head.html This is used to import web font from google

<link
  href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700;800;900&display=swap"
  rel="stylesheet"
/>

vuetify_storybook.js This file contains the vuetify configuration, in order to have the vuetify components, the themes and my icons working in storybook.

import Vue from 'vue'
import * as _Vuetify from 'vuetify/lib'
import themes from '@/plugins/my-themes'
import icons from '@/plugins/my-icons'

const Vuetify = _Vuetify.default

const isVueComponent = obj => obj.name === 'VueComponent'

const VComponents = Object.keys(_Vuetify).reduce((acc, key) => {
  if (isVueComponent(_Vuetify[key])) {
    acc[key] = _Vuetify[key]
  }
  return acc
}, {})

Vue.use(Vuetify, {
  components: {
    ...VComponents
  }
})


export default new Vuetify({
  icons: {
    values: icons
  },
  theme: {
    options: {
      customProperties: true
    },
    themes: themes
  }
})

vuetify_style.scss This file is used to modify the min-height in v-application, in order to avoid the story canvas to extend to end of the page, but just as big as the component is.

.v-application {
.v-application--wrap {
min-height:0;
}
}

Hope this helps…cheers guys!

@mrtwinkler for me this works with storybook 6.0.13 and vuetify 2.3.9 with https://storybook.nuxtjs.org/manual-setup/ after running npx nuxt storybook eject

storybook/preview.js:

import Vuetify from 'vuetify'
import colors from 'vuetify/es5/util/colors'
import 'vuetify/dist/vuetify.min.css'; // all the css for components

const vuetifyConfig = new Vuetify({
  theme: {
    dark: false,
    themes: {
      dark: {
        teal: colors.amber,
        primary: colors.blue.darken2,
        accent: colors.grey.darken3,
        secondary: colors.amber.darken3,
        info: colors.teal.lighten1,
        warning: colors.amber.base,
        error: colors.deepOrange.accent4,
        success: colors.green.accent3
      }
    }
  }
})

export const decorators = [(_) => {
  return {
    vuetify: vuetifyConfig,
    template: `
      <v-app>
        <v-main>
          <v-container fluid>
            <story />
          </v-container>
        </v-main>
      </v-app>`
  }
}]

I found this : https://github.com/nidkil/vuetify-with-storybook

maybe it can help you ?

I also am experiencing this