storybookjs / vue-cli-plugin-storybook

Vue CLI plugin for Storybook
MIT License
279 stars 44 forks source link

Problems with components using vuetify. #116

Open Kezhich opened 3 years ago

Kezhich commented 3 years ago

Hi. I'm stuck with adding vuetify to my stories. I'm using vue CLI 4.5.7 with vue 2.6.11

Most of the components dont work correctly and i can't access vuetify global variables.

I have these errors in console:

TypeError: Cannot read property 'smAndDown' of undefined
    at Clients-and-projects-card.vue?22d9:205
    at Proxy.renderList (vue.esm.js:2639)
    at Proxy.render (Clients-and-projects-card.vue?22d9:165)
    at VueComponent.Vue._render (vue.esm.js:3557)
    at VueComponent.updateComponent (vue.esm.js:4075)
    at Watcher.get (vue.esm.js:4488)
    at new Watcher (vue.esm.js:4477)
    at mountComponent (vue.esm.js:4082)
    at VueComponent.push../node_modules/vue/dist/vue.esm.js.Vue.$mount (vue.esm.js:9063)
    at VueComponent.push../node_modules/vue/dist/vue.esm.js.Vue.$mount (vue.esm.js:11974)

    vue.esm.js:628 [Vue warn]: Unknown custom element: <v-app> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

    vue.esm.js:628 [Vue warn]: Unknown custom element: <v-main> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

Any idea on how to fix this?

My current package.json chunk:

"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "storybook:build": "vue-cli-service storybook:build -c config/storybook",
    "storybook:serve": "vue-cli-service storybook:serve -p 6006 -c config/storybook"
  },
  "dependencies": {
    "axios": "^0.20.0",
    "core-js": "^3.6.5",
    "moment": "^2.29.0",
    "swiper": "^6.3.5",
    "v-tooltip": "^2.0.3",
    "vue": "^2.6.11",
    "vue-awesome-swiper": "^4.1.1",
    "vue-mq": "^1.0.1",
    "vue-ripple-directive": "^2.0.1",
    "vue-router": "^3.2.0",
    "vuetify": "^2.2.11",
    "vuex": "^3.4.0",
    "vuex-map-fields": "^1.4.1"
  },
  "devDependencies": {
    "@storybook/addon-essentials": "^6.0.26",
    "@storybook/addon-links": "^6.0.26",
    "@storybook/vue": "^6.0.26",
    "@typescript-eslint/eslint-plugin": "^2.33.0",
    "@typescript-eslint/parser": "^2.33.0",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-typescript": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/eslint-config-airbnb": "^5.1.0",
    "@vue/eslint-config-prettier": "^6.0.0",
    "@vue/eslint-config-typescript": "^5.0.2",
    "class-transformer": "^0.3.1",
    "eslint": "^6.7.2",
    "eslint-loader": "^4.0.2",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-vue": "^6.2.2",
    "prettier": "^1.19.1",
    "pug": "^3.0.0",
    "pug-lint-vue": "^0.4.0",
    "pug-plain-loader": "^1.0.0",
    "sass": "^1.26.5",
    "sass-loader": "^8.0.2",
    "typescript": "~3.9.3",
    "vue-cli-plugin-storybook": "~2.0.0",
    "vue-cli-plugin-vuetify": "~2.0.8",
    "vue-template-compiler": "^2.6.11",
    "vuetify-loader": "^1.3.0"
  }

My vuetify plugin config:

import Vue from 'vue';
/* @ts-ignore */
import Vuetify from 'vuetify/lib/framework';
import ru from 'vuetify/src/locale/ru';
import localIcons from '@components/elements/el-icon/paths';

Vue.use(Vuetify);

export default new Vuetify({
    lang: {
        locales: { ru },
        current: 'ru',
    },
    theme: {
        options: {
          customProperties: true
        },
        themes: {
          light: {
            primary: '#071AC3',
            secondary: '#424242',
            accent: '#82B1FF',
            error: '#FF5252',
            info: '#2196F3',
            success: '#4CAF50',
            warning: '#12A54D'
          }
        }
      },
      customVariables: ['~/assets/scss/variables.scss'],
      treeShake: true,
    icons: {
        values: {
            ...localIcons
        },
    },
});

Storybook config main.js:

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

Storybook config preview.js:

import '../../src/assets/scss/_reset.scss';
import '../../src/assets/scss/_variables.scss';
import '../../src/assets/scss/_mixins.scss';
import '../../src/assets/scss/_font-face.scss';
import '../../src/assets/scss/_base.scss';

import '@filters/';
import '@plugins/';
import '@components/';
import Vue from 'vue';
import vuetify from '@plugins/vuetify/index';
import 'vuetify/dist/vuetify.min.css';

// Один контейнер для всех компонентов
import { addDecorator } from '@storybook/vue';

Vue.use(vuetify);

addDecorator(() => ({
    vuetify,
    template: `<v-app><v-main><section class="container"><story /></section></v-main></v-app>`,
}));

export const parameters = {
    layout: 'centered',
    backgrounds: {
        values: [
            { name: 'white', value: '#fff' },
            { name: 'black', value: '#000' },
        ],
    },
};
WebersonRodrigues commented 3 years ago

Do you have any palliative solutions to this situation?

farrago commented 3 years ago

I've come up with a solution to this, though being new to storybook I can't guarantee it's correct.

I added https://storybook.js.org/addons/@socheatsok78/storybook-addon-vuetify/ to my vue project, but importantly where those instructions tell you to edit .storybook/<file>.js you actually need to edit config/storybook/<file.js> because that's the new directory that vue cli storybook plugin uses for the config when building storybook.

What I did to make it work was:

First, edit config/storybook/main.js (the new central config file) to add in the veutify addon:

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

Then create a config/storybook/preview.js with:

import { withVuetify } from '@socheatsok78/storybook-addon-vuetify/dist/decorators'

export const decorators = [
    withVuetify
];

Then testing with a Veutify based component started rendering the component correctly.

adambullmer commented 2 years ago

As an additional potential solution, I've made this decorator, where AppDecorator is a component that will render <v-app> and <v-main>, among other implementation specific global needs:

import Vue, { VueConstructor } from "vue";
import { makeDecorator } from "@storybook/addons";

import vuetify from "@/plugins/vuetify";
import AppDecorator from "@/components/AppDecorator.vue";

export default makeDecorator({
  name: "withVuetify",
  parameterName: "vuetify",
  wrapper: (storyFn, context, { parameters = {} }) => {
    const WrappedComponent = storyFn(context) as VueConstructor<Vue>;

    return Vue.extend({
      vuetify,
      components: { AppDecorator, WrappedComponent },
      template: `<app-decorator><wrapped-component /></app-decorator>`,
    });
  },
});

For me, the thing I see different from the original decorator is the use of the wrapper creating a wrapped vue component along with injecting it into the decorator vue component. It was my understanding that the default template will be rendered with react, so I imaging that the original implementation would be throwing errors for unknown custom components.