4 tips to use Storybook in a Vue project
Tags: vue, storybook
Published: 2021-06-01 15:44:13

At [Scalingo](https://scalingo.com/) we are a Platform as a Service and we recently revamp the dashboard used by all our clients.
We were able to speed up our development process thanks to 

Today I'll share our best tips and tricks to use Storybook in a Vue project.

This article was initially published on Scalingo.com. You can find the full article [here](https://scalingo.com/blog/guide-storybook-vue-js).

### Tip 1 : Use js format, not mdx

Storybook offers two stories formats: js and [mdx](https://mdxjs.com/) (mdx are md files, with the ability to have js sections). We initially picked the mdx format for its improved documentation capabilities. Turn out it was bad idea.

Indeed we did not use the mdx extra features and maintenance with mdx is particularly harder.

It was better to have separate md files for the few points we wanted to document and to use the “more standard” js format. The reason is, especially with Vue.js, you will have less bugs and more documentation online with the js format.

### Tip 2: VueDevTools in Storybook (quick hack)

The [VueDevTools](https://github.com/vuejs/vue-devtools) does not work in canvas mode, but works if the canvas is open in a new tab (top left second icon).

### Tip 3 : Separate concerns of your components (Controller/Views…)

We made the choice to separate concerns of our components.

Concretely, we have three components types: controllers, views, design system. Controllers components are the only one authorized to interact with model (services, store). Consequently, this allows us to have all others component as “pure” visual components, piloted only via “dumb” props.

It leads to easy creation/update of complex views component, via dumb flat json files

```javascript
import Projects from "@/components/views/Projects";
import currentUser from "@/stories/data/currentUser.json";
import props from "./props.json";
export default {
  title: "Views/Main/Apps",
  component: Projects,
};
const Template = (args, { argTypes }) => ({
  props: Object.keys(argTypes),
  components: { Projects },
  template: `<Projects v-bind="$props">`,
});
export const Default = Template.bind({});
Default.args = {
  user: currentUser,
  ...props,
};
```

If your component is already functional in a browser, you can use the VueDevTools/component tab to copy the props and paste them in the json file.

![https://www.datocms-assets.com/36416/1621237728-vuedevtools-component-tab.png?fit=crop&fm=jpg&w=825](https://www.datocms-assets.com/36416/1621237728-vuedevtools-component-tab.png?fit=crop&fm=jpg&w=825)

### Tip 4 : Add StoriesWrapper around your stories

There are at least two different reasons to add a wrapper around your stories.

In our case we use nested routing. So the final view component is, in the real app, wrapped around N components. If you have a router, the view is at least wrapped in the App component. Stories wrapper is here to reproduce this “wrapped” environment.

The second reason: the wrapper can also help you control finely the canvas parameters.

Here our preview.js configuration, with our two additional toolbar menus “i18n” and “theme”

```javascript
// config/storybook/preview.js
export const globalTypes = {
  language: {
    name: "i18n",
    description: "i18n selector",
    defaultValue: "en",
    toolbar: {
      items: ["en", "fr"],
    },
  },
  theme: {
    name: "theme",
    description: "theme selector",
    defaultValue: "light",
    toolbar: {
      items: ["light", "dark"],
    },
  },
};
const appSbProvider = (Story, context) => ({
  template: "<story/>",
  data() {
    return { theme: context.globals.theme, language: context.globals.language };
  },
});
export const decorators = [appSbProvider];
```

And how we use it in our a child called in all our stories wrappers

```javascript
// src/components/others/storybook/AppSb.vue
export default {
  name: "AppSb",
  ...
  created() {
    this.changeLanguage(this.$root.$children[0].language);
    this.changeTheme(this.$root.$children[0].theme);
  },
  ...
};
```

It is allowing us to mount “app like” view stories, without too much effort. And control them via the Storybook toolbar.

```javascript
// The Storybook wrapper
import WelcomeSb from "@/components/others/storybook/WelcomeSb";
// The component we want to storify
import Projects from "@/components/views/Projects";
// Flat Props in json files
import currentUser from "@/stories/data/currentUser.json";
import props from "./props.json";
export default {
  title: "Views/Main/Apps",
  component: Projects,
};
const Template = (args, { argTypes }) => ({
  props: Object.keys(argTypes),
  components: { Projects, WelcomeSb },
  template: `<WelcomeSb selectedRoute="Projects"><Projects v-bind="$props"></Projects></WelcomeSb>`,
});
export const Default = Template.bind({});
Default.args = {
  user: currentUser,
  ...props,
};
```

## Conclusion

Here are 4 tips from Scalingo as we are heavy users of Storybook!

Feel free to check our full [guide about Storybook](https://scalingo.com/blog/guide-storybook-vue-js) in a Vue.js project on our blog or the first part of this blog post on [dev.to](https://dev.to/scalingo/storybook-in-a-vue-js-project-an-introduction-guide-4i9n) 

And if you need hosting without having to handle servers, feel free to check us out!