# Documenting components

Vue styleguidist generates documentation for your components based on the comments in your source code declarations and Readme files.

Note: See examples of documented components in our demo style guide.

# Code comments

Vue styleguidist will display the contents of your components' JSDoc comment blocks.

Note: Components and documentation comments are parsed by default by the vue-docgen-api library. You can change this behavior using propsParser options.

<template>
  <div class="Button">/* ... */</div>
</template>

<script>
  /**
   * The only true button.
   * @displayName Best Button
   */
  export default {
    name: 'Button',
    props: {
      /**
       * The color for the button.
       */
      color: {
        type: String,
        default: '#333'
      },
      /**
       * The size of the button
       * @values small, normal, large
       */
      size: {
        type: String,
        default: 'normal'
      },
      /**
       * Gets called when the user clicks on the button
       */
      onClick: {
        type: Function,
        default: event => {
          console.log('You have clicked me!', event.target)
        }
      }
    }
    /* ... */
  }
</script>

Note the use of the @displayName tag to change the displayed name of your component. This top-level comment block must come before the export default in your script tag.

If you want to document a custom v-model (opens new window), you have to add model tag in comment

<script>
  export default {
    name: 'my-checkbox',
    props: {
      /**
       * @model
       */
      value: String
    }
  }
</script>

# Available Tags

You can use the following tags when documenting components, props and methods.

# @values

A common pattern in VueJs components is to have a limited number of valid values for a prop.

For instance, size would only accept small, medium and large.

To document this in styleguidist, use the @values tag:

export default = {
    props: {
      /**
       * The size of the button
       * @values small, normal, large
       */
      size: {
        type: String,
        default: 'normal'
      }
    }
}

See also:

# @example

Provide an example of how to use a documented item. The text that follows this tag will be displayed as highlighted code.

See also:

# @deprecated

The @deprecated tag marks a symbol in your code as being deprecated:

/**
 * An example-less button.
 * @deprecated Use the [only true button component](#button) instead
 */

See also:

# @author

# @since

# @version

# @ignore

By default, all props your components have are considered to be public and are published. In some rare cases, you might want to remove a prop from the documentation while keeping it in the code. The @ignore tag allows you to do this. See here for more:

# Events

For events documentation, add a comment right above it. If your comment is at the start of the function, the event will not be picked up.

# In script block

If the event is explicitly specified, no need to tell styleguidist what it is.

/**
 * Success event.
 */
this.$emit('success')

Constants will be recognized too

/**
 * Success event.
 */
const success = 'succ'
this.$emit(success)

If your event name comes from an object, precise the @event tag

/**
 * Success event.
 *
 * @event success
 */
this.$emit(EVENTS.success)

If your event returns arguments/properties use the @property tag to describe them

Use @arg or @param if you prefer

/**
 * Triggers when the number changes
 *
 * @property {number} newValue new value set
 * @property {number} oldValue value that was set before the change
 */
this.$emit('change', newValue, oldValue)

# In template

Events emitted directly in v-on expressions will be detected automatically. To document them further, in the template, add a comment above the line where the $emit() is called.

The comment block containing the documentation needs to contain one line with @event click. The rest of the comment block will behave like the comment blocks described in the script.

@property to describe an argument and no tag at all to set the description of the event.

<div>
  <!--
    triggered on click
    @event click
    @property {object} demo - example
    @property {number} called - test called
  -->
  <button @click="$emit('click', test)"></button>
</div>

# Slots

Static slots are automatically documented by styleguidist.

# In the template

To add a description, add a comment right before.

<template>
  <div class="modal">
    <div class="modal-container">
      <div class="modal-head">
        <!-- @slot Use this slot header -->
        <slot name="head"></slot>
      </div>
      <div class="modal-body">
        <!-- @slot Use this slot body -->
        <slot name="body"></slot>
      </div>
    </div>
  </div>
</template>

In addition to documenting the slots and giving them a description, you can document the bindings. They are documented like props or params using the keyword @binding,

The format will then be

<!--
  @binding {type} BindingName description of what the bindings is meant for
  -->

example of a real documented slot

<div slot-scope="row" class="list-item1">
  {{row.item.text}}
  <!--
  	@slot Menu Item footer
		@binding {object} icon icon of the menu item
		@binding {string} text text of the menu item
	-->
  <slot name="test" :icon="row.item.icon" :text="row.item.text" />
</div>

To get a bit deeper, check out the ScopedSlot component in the basic example. Read the code (opens new window) and see how it is rendered in the live example (opens new window)

Note: The docblock must be part of the same comment block. Multiple individual comments do not get parsed together.

Note 2: From 4.44.0, you can use JS comments blocks if you choose to. The syntax is the same as in HTML. One constraint: the comment should be the only content of the interpolation:

  • Valid comment:
  • Invalid comment: NaN.

# In a render function

If your component is rendered using jsx, tsx or is using the render function styleguidist will still try to detect your slots.

Here are two examples that are detected and documented:

Detect a default slot

export default {
  render(createElement) {
    return createElement('div', [
      /**
       * @slot The header
       * @binding {object} menuItem the menu item
       */
      this.$scopedSlots.default({
        menuItem: this.message
      })
    ])
  }
}

In a functional component:

export default {
  functional: true,
  render: function (createElement, { data, children: cld }) {
    /* @slot describe destructured default */
    return createElement('div', data, cld)
  }
}

If vue-styleguidist does not detect your slots, you can explicitly tell it with a comment block before the render function:

export default {
  /**
   * Place the content of your menuitem here,
   * the value of index and content will be passed down to you
   * @slot menuContent
   * @binding {number} index the index in the list
   * @binding {string} content text of the item
   */
  render: function () {
    // ...
  }
}

If you have multiple slots, place multiple blocks one after another:

export default {
  /**
   * @slot content
   */
  /**
   * @slot icon
   */
  render: function () {
    // ...
  }
}

# Include Mixins and Extends

If you import a mixin (opens new window) or extends (opens new window) it will automatically be added to your main component

# Usage examples and Readme files

Vue styleguidist will look for any Readme.md or ComponentName.md files in the component's folder and display them. Any code block with a language tag of vue, js, jsx, javascript or html will be rendered as a Vue component with an interactive playground.

If you want to ignore the readme file for one component, use the @example [none] doclet. Use this when multiple components in the same folder share a ReadMe file. This will prevent the examples from being rendered multiple times.

Vue component example:

```jsx
    <Button size="large">Push Me</Button>
```

One more with generic code fence:

```
<Button size="large">Push Me</Button>
```

You can disable an editor by passing a `noeditor` modifier:

```jsx noeditor
<Button>Push Me</Button>
```

To render an example as highlighted source code add a `static` modifier:

```jsx static
<Button>Push Me</Button>
```

You can also initialize vue to construct more complex examples in two ways:

1. Create a new Vue instance

```js
const names = require('dog-names').all;

new Vue({
  data(){
    return {
      list: names
    }
  },
  template: `
    <div>
      <RandomButton :variants="list" />
    </div>
  `
})
```

2. Single-file components with a language tag of vue (supports <style scoped>)

```vue
  <template>
    <div class="wrapper">
      <Button id="dog-name-button" @click.native="pushButton">Push Me</Button>
      <hr />
      <p class="text-name">Next Dog Name: </p>
    </div>
  </template>

  <script>
    const dogNames = require('dog-names').all;

    // You can also use 'exports.default = {}' style module exports.
    export default {
      data() {
        return { numClicks: 0, dogName: dogNames[0] };
      },
      methods: {
        pushButton() {
          this.numClicks += 1;
          this.dogName = dogNames[this.numClicks];
        }
      }
    }
  </script>

  <style scoped>
    .wrapper {
      background: blue;
    }
    .text-name {
      color: red;
    }
  </style>
```

Examples with all other languages are rendered only as highlighted source code, not an actual component:

```html
<Button size="large">Push Me</Button>
```

Any [Markdown](http://daringfireball.net/projects/markdown/) is **allowed** _here_.

Note: You can configure examples file name with the getExampleFilename option.

You can also add the custom block (opens new window) <docs></docs> inside *.vue files, so that vue styleguidist builds the readme. You can review the following example (opens new window)

# External examples using doclet tags

Additional example files can be associated with components using @example doclet syntax.

The following component will also have an example loaded from the extra.examples.md file:

/**
 * Component is described here.
 *
 * @example ./extra.examples.md
 */
export default {
  name: 'Button'
  // ...
}

Note: You’ll need a regular example file (like Readme.md) too when skipComponentsWithoutExample is true.

# Ignore examples files

The @examples doclet can also be used to ignore the connected ReadMe file. Use it to avoid rendering examples multiple times.

/**
 * Component is described here.
 *
 * @example [none]
 */
export default {
  name: 'Button'
  // ...
}

# Public methods

By default, any methods your components have are considered to be private and are not published. Mark your public methods with JSDoc @public (opens new window) tag to get them published in the docs:

/**
 * Insert text at cursor position.
 *
 * @param {string} text
 * @public
 */
insertAtCursor(text) {
  // ...
}

# Ignoring props

By default, all props your components have are considered to be public and are published. In some rare cases, you might want to remove a prop from the documentation while keeping it in the code. To do so, mark the prop with JSDoc @ignore (opens new window) tag to remove it from the docs:

  props: {
    /**
    * @ignore
    */
    color: {
      type: String,
      default: '#333'
    }

# displayName

In addition to those tags, you can use @displayName to change the name displayed in your style guide. Know that since it's visual name has changed, it's calling name is now The letters of it, without space or punctuation.

For instance, if the display name is set as

/**
 * @displayName Wonderful Button
 **/

To reference it in examples, one has to call <WonderfulButton/>. See to How to use component name in docs with a different displayName

# Methods

When documenting methods you can also use:

Documenting events:

Documenting v-model:

  • @model

Tags can even render Markdown.

You can mark your public methods with JSDoc @public tag to get them published in the docs.

<template>
  <!-- -->
</template>

<script>
  /**
   * The only true button.
   * @version 1.0.1
   */
  export default {
    name: 'Button',
    props: {
      /**
       * The color for the button.
       * @see See [Wikipedia](https://en.wikipedia.org/wiki/Web_colors#HTML_color_names)
       * @see See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) for a list of color names
       */
      color: {
        type: String,
        default: '#333'
      },
      /**
       * The size of the button
       * `small, normal, large`
       * @since Version 1.0.1
       */
      size: {
        type: String,
        default: 'normal'
      },
      /**
       * Gets called when the user clicks on the button
       */
      onClick: {
        type: Function,
        default: event => {
          console.log('You have clicked me!', event.target)
        }
      }
    },
    methods: {
      /**
       * Gets called when the user clicks on the button
       *
       * @param {SyntheticEvent} event The react `SyntheticEvent`
       * @param {Number} num Numbers of examples
       * @public This is a public method
       */
      launch(event, num) {
        /* ... */
      },
      // ...
      ignoreMethod() {
        /**
         * Success event.
         *
         * @event success
         * @type {object}
         */
        this.$emit('success', {})
      }
    }
    /* ... */
  }
</script>

# Composable Components

When a component is a list or a table it is easier to write it using a composition API.

For example, a dropdown element would be easier to read this way

<DropDown>
  <Choice val="1">value 1</Choice>
  <Choice val="2">value 2</Choice>
</DropDown>

than with a prop

<DropDown
  :choices="[{val:1,text:'value 1'}, {val:2,text:'value 2'}]"
/>

Here is how Vue Styleguidist helps document this pattern: Add a @requires doclet to the main component to signify what components documentation to include in the same page. In every example, the extra component will be automatically registered the same way the main component already is.

# Example

In the previous example we have a DropDown component that requires a Choice component to render properly. Here is what the component DropDown.vue should look like.

<template>
  <select>
    <slot />
  </select>
</template>

<script>
/**
 * @requires ./Choice.vue
 */
export default {
  name: 'DropDown'
}
</script>

NOTE: Now Choice will be documented only as a part of DropDown. It will not have its own page or its own examples. Its props will be displayed with DropDowns, and it will be made available in DropDowns examples.

# TypeScript, Flow and Class-style Components

Vue Styleguidist understands TypeScript & Flow annotations. Write components in a typed language, types are documented automatically. It is compatible with class style components as well, with or without TypeScript.

import { Component, Prop, Vue } from 'vue-property-decorator'

@Component({
  name: 'ClassButton'
})
export default class MyComponent extends Vue {
  aHiddenData: string = ''

  /**
   * prop typed through the decorators arguments
   */
  @Prop({ type: String })
  propNoType = ''

  /**
   * prop typed through an annotation
   */
  @Prop() propA: number = 0

  /**
   * prop with a default value
   */
  @Prop({ default: 'default value' })
  propB: string = 'hello'

  /**
   * prop with a hybrid type
   */
  @Prop() propC: string | boolean = false

  /**
   * method testing
   * @public
   */
  onClick(a: string) {
    /**
     * Success event when we click
     */
    this.$emit('success', a)
  }
}

Notice how onClick parameter a does not need type documentation.

# JSX

vue styleguidist understands JSX component templates too. In this example, it will display the definition of the found slot.

export default {
  render() {
    return (
      <div>
        {/** @slot Use this slot to have a header */}
        <slot name="header" />
        {this.contentText}
      </div>
    )
  }
}

# Setup syntax

In vue 3, VueJs introduced the setup syntax (opens new window). This greatly helps readability of components. It also makes a much more performant TypeScript type checking.

From version 4.44.0, Vue Styleguidist allows to document the props & events defined with this syntax.

# Props

In JavaScript, add a comment above the property in the object passed to defineProps(). In this comment, use the same principle as regular syntax Props.

defineProps({
  /**
   * Should the prop be required?
   * @link https://v3.vuejs.org/
   */
  testProp: {
    type: Boolean,
    required: true
  }
})

The same goes for TypeScript components:

defineProps<{
  /**
   * A very nice prop, now accepting numbers
   */
  testProp: number
  /**
   * An old prop
   * @deprecated prefer using the other prop
   */
  anotherTestProps?: boolean
}>()

# Events

Events are all defined using the defineEmits() function. Document them in comments before your events entries.

const emit = defineEmits({
  /**
   * Document your event here
   * @arg {string} payload - The first argument
   */
  submit: payload => {
    if (payload.email && payload.password) {
      return true
    } else {
      console.warn('Invalid submit event payload!')
      return false
    }
  }
})

and in TypeScript

interface Format {
  email: string
  password: string
}

const emit = defineEmits<{
  /**
   * Cancels everything
   */
  (event: 'cancel'): void
  /**
   * Save the world
   * @arg {{ email: string, password: string }} payload - The payload
   */
  (event: 'save', payload: Format): void
}>()

NOTE: Remember to document complex argument types in the comment above the event. Docgen does not parse types and will only display their names.

# Writing code examples

Code examples in Markdown use the ES6 syntax. They can access all the components of your style guide using global variables:

<Panel>
  <p>
    Using the Button component in the example of the Panel component:
  </p>
  <Button>Push Me</Button>
</Panel>

Note: Vue styleguidist uses Bublé (opens new window) to run ES6 code on the frontend, it supports most of the ES6 features (opens new window).

You can also import other modules (e.g. mock data that you use in your unit tests) from examples in Markdown:

const mockData = require('./mocks');
<Message :content="mockData.hello" />

Note: If you need a more complex demo, define it in a separate JavaScript file and import it in Markdown. If the component file is in the same folder as the markdown, write import { myExample as exam } from './myExample'; You can then use this imported setup object in your examples. Note that the code for the setup will not appear in the documentation.

import { myExample as Button } from './myExample'
;<div>
  <Button />
</div>

Note If you prefer to use JSX in your examples, use the jsxInExample option in your styleguide.config.js. Using this option will force you to use proper Vue format for your examples. No more pseudo-JSX code.

This would not work with the jsxInExample option

<Button />

...while this would be valid

export default {
  render() {
    return <Button />
  }
}

# Importing examples

To make autocomplete and syntax highlighting practical, one can as well import examples from external files. In the following example ./myExample.vue will be used as an example.

```[import](./myExample.vue)
Text typed here will be entirely ignored. You can use it to describe the example imported for maintenance purposes
```

Note This option DOES NOT replace automatically examples code with vue-docgen-cli. Since the rendering engine is only copying the contents of the markdown without parsing it, the CLI can't know what content to replace.

Note No need to specify the language as it will be inferred from the name of the file

Note All flags described here can still be used