82. Creating live component previews

One of the most interesting features of Vue Styleguidist is that it allows us to render a component within the documentation site, giving the reader a live, interactive preview of that component.

To get this working, we just need to declare the component in a js code block in our docs tag. Let me show you how in this PageFooter component.

Firstly, we create the docs tags. Then, we'll add the heading ### Usage example, which is not required but I think makes it looks nicer. Next, we create a ...js code block. And inside that, we'll declare the markup which is simply <PageFooter />

client/components/PageFooter.vue

<docs>
  ### Usage example
  ``js
  <PageFooter />
  ``
</docs>

Let's now take a look at Page Footer component in the docs site. We can see the "Usage Example" heading, but we don't actually see the component rendered.

If we take a look in the console we can see why: after a few warnings we have a Type Error "Cannot read property 'breakpoint' of undefined".

This is because the Page Footer template attempts to access Vuetify's breakpoint property and the Vuetify plugin is not present in the context of where this component is mounted.

Container

So the challenge we have is that most of our components have dependencies of some sort, including Vuetify, Vuex, Vue Auth and so on.

So what we'll need to do is set up a wrapper component that we can use to wrap any components being previewed in the docs. This wrapper component will have all the required dependencies added as global properties, therefore the preview components will have access to them.

So let's go to the terminal, kill our dev server, and create a subfolder in the docs directory where we can put the wrapper component and other files related to the styleguide.

So we'll go:

$ mkdir -p docs/styleguide

What we're actually going to do is create a factory function that generates wrapper components. So let's create a new JavaScript module file by going:

$ touch docs/styleguide/wrapper.js

Wrapper factory

Let's now open this new file and we'll begin by exporting a function. This function will take an argument which is the render function of the component being previewed. So lets put export default component => {};.

Since this is a factory function, we need to return a component config object. So inside the function, let's add return {};.

Let's then give the component a name property and name it "Wrapper". This will help with debugging in Vue Devtools.

Finally, for this to work, the wrapper instance must declare the preview component in it's own template or render function. Let's go with the latter option and add a function property render, pass in h as an argument, and in the body return h(component).

docs/styleguide/wrapper.js

export default component => {
  return {
    name: "Wrapper",
    render (h) {
      return h(component);
    }
  }
};

Render root JSX

We now need to tell Vue Styleguidist to call our wrapper component factory when previewing components. To do this, we add the property renderRootJsx to the styleguide config, and then specify the file we created, "./docs/styleguide/wrapper.js"

styleguide.config.js

module.exports = {
  ...
  renderRootJsx: "./docs/styleguide/wrapper.js",
};

After that, you'll now need to restart the styleguide dev server.

[restart dev server]

Looking in the browser console again, you'll see that we still have the same errors, since we haven't directly dealt with the missing dependency issue yet.

However, if we look in Vue Devtools at the components tab, you'll see that we now have our Wrapper component, which includes another anonymous component, and inside that, we have our PageFooter component.

So the first part of our solution is working.

Naming comtainer

As we just saw, Vue Styleguidist already wraps the preview component in another component. That's no problem, but let's give that a component a name so we understand what's going on when debugging.

We can give the component that's passed in a name property and call it "PreviewContainer".

docs/styleguide/wrapper.js

export default component => {
  component.name = "PreviewContainer";
  return {
    name: "Wrapper",
    render (h) {
      return h(component);
    }
  }
};

If we look in Vue Devtools now, we'll see a clearly named component hierarchy.

Discussion

0 comments