1
votes

I'm developing a Vue app with Vuetify and also document the components with Storybook.

I'm writing the stories nicely, all components seem to show up in Storybook (like my custom components & the Vuetify components too). Except for VIcon.

I have a component that uses Vuetify's VIcon, and I couldn't get the icon to show up (in the real app there's no problem with that).

The setup:

src/plugins/vuetify.js

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

Vue.use(Vuetify);

export default new Vuetify({
  icons: {
    iconfont: 'mdiSvg',
  }
});

.storybook/vuetify_storybook.js

import Vue from 'vue';
import Vuetify from 'vuetify'; // loads all components
import 'vuetify/dist/vuetify.min.css'; // all the css for components
import config from '@/plugins/vuetify'; // basic config with theme

Vue.use(Vuetify);

export default new Vuetify(config);

.storybook/preview.js

import { addDecorator } from '@storybook/vue';
import vuetify from './vuetify_storybook';

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

.storybook/main.js

const path = require('path');

module.exports = {
  stories: [
    '../stories/**/*.stories.js',
    '../src/**/*.stories.js'
  ],
  addons: [
    '@storybook/addon-actions',
    '@storybook/addon-links',
    '@storybook/addon-knobs',
    '@storybook/addon-storysource'
  ],

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

    config.resolve.extensions.push('.vue', '.css', '.less', '.scss', '.sass', '.html')

    // Use Sass loader for vuetify components
    config.module.rules.push({
      test: /\.sass$/,
      use: ['style-loader', 'css-loader', 'sass-loader'],
      include: path.resolve(__dirname, '../'),
    });

    config.module.rules.push({
      test: /\.scss$/,
      use: [
        'vue-style-loader',
        'css-loader',
        {
          loader: 'sass-loader',
          options: {
            additionalData: "@import '@/styles/variables.scss';"
          }
        }
      ],
    });

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

    // Return the altered config
    return config;
  },
};

CustomVIcon.stories.js

import { withKnobs } from '@storybook/addon-knobs'

export default {
  title: 'Display that icon',
  decorators: [withKnobs]
}

export const displayIcon = () => {
  return {
    template: `<v-icon>mdi-alert</v-icon>`
  }
}

If I add a text that is not an mdi icon (like <v-icon>notmditext</v-icon>, then the text is displayed - but as soon as I add a - (dash/minus sign) to the string, it doesn't show up.

I can see the icon's HTML (well, part of it) in the console, only the ::before part is missing (that should be the actual icon). So styles are set, classes are added, etc when I inspect the Storybook page (where the icon should be).

  • Already tried adding https://www.npmjs.com/package/storybook-addon-jsx (as in the real case the component is rendered with JSX), nothing changed (no v-icon)
  • Already tried putting other components in the story (like VCard), and they showed up (and other stories work just perfectly)
  • Vue is 2.6.12, Vuetify 2.3.10, @storybook/vue 6.0.21 - so quite fresh
  • Also tried to import components from vuetify/lib (and not just vuetify) in the .storybook/vuetify_storybook.js & registering them locally (in the preview.js and the story file - no change)
1
might be a long shot, but is it possible some other CSS is setting the content property of your :before to none? Because that would effectively remove them which kind of forbids inspection. As a test, you could set the before's content property with !important and see if it renders. That will allow you to inspect the element and therefore see where the none (now overridden) is coming from. Is there any chance you could set up a minimal reproducible example?tao
@tao thanks for the idea - unfortunately I couldn't have set it by hand, as Vuetify "hides" this. I tried to think of creating a minimal, reproducible example, but it could've taken serious time to do that, so I kept it only for last resort (setting up EVERYTHING as in my dev environment AND reducing the problem... Vue, Vuetify, Storybook, link them together, etc.... Ahhhh :) ). But if no idea had come for cca. two-three days, then I would've done it. Anyways - thanks for the quick response.muka.gergely

1 Answers

2
votes

OK, just needed another view on the things:

  • removed the link to the Material design icons CDN:
// remove this from public/index.html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
  • changed the package from @mdi/js to @mdi/font
npm remove @mdi/js
npm install @mdi/font -D
  • imported the corresponding CSS in two places:
// add this to src/main.js & .storybook/vuetify_storybook.js
import '@mdi/font/css/materialdesignicons.css';
  • changed the Vuetify config
// in src/plugins/vuetify.js
icons: {
  // iconfont: 'mdiSvg', // change this
  iconfont: 'mdi', // to this
},

AND VOILÁ! VIcon shows up.

So, the problem was that I thought everything had been set up correctly, but it wasn't the case: the icons in the app were coming from the CDN (have not looked at the Network tab), and when I removed the CDN link from the index.html it immediately became apparent.

More on setting up the icons in Vuetify: Install Material Design Icons