storybook/docs/get-started/vue-vite.md
Kyle Gach 8f2a88af50 Apply suggestions from code review
Co-authored-by: Lars Rickert <dev@lars-rickert.de>
2024-03-06 13:49:53 -07:00

7.3 KiB
Raw Blame History

title
Storybook for Vue & Vite

Storybook for Vue & Vite is a framework that makes it easy to develop and test UI components in isolation for Vue applications built with Vite. It includes:

  • TK - Emoji feature list
  • 💫 and more!

Requirements

  • Vue >= 3
  • Vite >= 3.0 (4.X recommended)
  • Storybook >= 7.0

Getting started

In a project without Storybook

Follow the prompts after running this command in your Next.js project's root directory:

<CodeSnippets paths={[ 'common/init-command.npx.js.mdx', 'common/init-command.yarn.js.mdx', 'common/init-command.pnpm.js.mdx', ]} />

More on getting started with Storybook.

In a project with Storybook

This framework is designed to work with Storybook 7. If youre not already using v7, upgrade with this command:

<CodeSnippets paths={[ 'common/storybook-upgrade.npm.js.mdx', 'common/storybook-upgrade.pnpm.js.mdx', 'common/storybook-upgrade.yarn.js.mdx' ]} />

Automatic migration

When running the upgrade command above, you should get a prompt asking you to migrate to @storybook/vue3-vite, which should handle everything for you. In case that auto-migration does not work for your project, refer to the manual migration below.

Manual migration

First, install the framework:

<CodeSnippets paths={[ 'vue/vue3-vite-install.npm.js.mdx', 'vue/vue3-vite-install.pnpm.js.mdx', 'vue/vue3-vite-install.yarn.js.mdx' ]} />

Then, update your .storybook/main.js|ts to change the framework property:

<CodeSnippets paths={[ 'vue/vue3-vite-add-framework.js.mdx', 'vue/vue3-vite-add-framework.ts.mdx' ]} />

Extending the Vue application

Storybook creates a Vue 3 application for your component preview. When using global custom components (app.component), directives (app.directive), extensions (app.use), or other application methods, you will need to configure those in the ./storybook/preview.js file.

Therefore, Storybook provides you with a setup function exported from this package, which receives as a callback your Storybook instance, which you can interact with and add your custom configuration.

// .storybook/preview.js
import { setup } from '@storybook/vue3';

setup((app) => {
  app.use(MyPlugin);
  app.component('my-component', MyComponent);
  app.mixin({
    /* My mixin */
  });
});

// Rest of the file...

Using vue-component-meta

vue-component-meta is a tool that extracts metadata from Vue components which is maintained by the official Vue team. Storybook can use it to generate the controls for your stories and documentation. It's a more full-featured alternative to vue-docgen-api and is recommended for most projects.

It requires Storybook >= 8. vue-component-meta is currently opt-in but will become the default in future versions of Storybook.

If you want to use vue-component-meta, you can configure it in your .storybook/main.js|ts file:

// .storybook/main.ts
import type { StorybookConfig } from '@storybook/vue3-vite';

const config: StorybookConfig = {
  framework: {
    name: '@storybook/vue3-vite',
    options: {
      docgen: 'vue-component-meta',
    },
  },
};

export default config;

vue-component-meta comes with many benefits and enables more documentation features, such as:

Support for multiple component types

vue-component-meta supports all types of Vue components (including SFC, functional, composition / options API components) from .vue, .ts, .tsx, .js, and .jsx files.

It also supports both default and named component exports.

Prop description and JSDoc tag annotations

To provide a description for a prop, including tags, you can use JSDoc comments in your component's props definition:

<!-- YourComponent.vue -->
<script setup lang="ts">
interface MyComponentProps {
  /**
   * The name of the user
   */
  name: string;
  /**
   * The category of the component
   *
   * @since 8.0.0
   */
  category?: string;
}

withDefaults(defineProps<MyComponentProps>(), {
  category: "Uncategorized",
});
</script>

Events types extraction

Due to technical limitations of Volar / vue language features, JSDoc descriptions for emitted events can not be extracted.

To provide a type for an emitted event, you can use TypeScript types in your component's defineEmits call:

<!-- YourComponent.vue -->
<script setup lang="ts">
  type MyFooEvent = 'foo';

  interface MyEvents {
    (event: MyFooEvent, data?: { foo: string }): void;
    (event: 'bar', value: { year: number; title?: any }): void;
    (e: 'baz'): void;
  }

  const emit = defineEmits<MyEvents>();
</script>

Which will generate the following controls:

Controls generated from events

Slots types extraction

The slot types are automatically extracted from your component definition and displayed in the controls panel.

<!-- YourComponent.vue -->
<template>
  <slot name="no-bind"></slot>
  <br />
  <slot :num="123"></slot>
  <br />
  <slot name="named" str="str"></slot>
  <br />
  <slot name="vbind" v-bind="{ num: 123, str: 'str' }"></slot>
</template>

<script setup lang="ts"></script>

The definition above will generate the following controls:

Controls generated from slots

If using defineSlots, the controls will even include the description:

defineSlots<{
  /** Example description no-bind. */
  noBind(props: {}): any;
  /** Example description default. */
  default(props: { num: number }): any;
  /** Example description named. */
  named(props: { str: string }): any;
  /** Example description vbind. */
  vbind(props: { num: number; str: string }): any;
}>();

### Exposed properties and methods

The properties and methods exposed by your component are automatically extracted and displayed in the controls panel.

```html
<!-- YourComponent.vue -->
<script setup lang="ts">
  import { ref } from 'vue';

  const label = ref('Button');
  const count = ref(100);

  defineExpose({
    /**
     * a label string
     */
    label,
    /**
     * a count number
     */
    count,
  });
</script>

The definition above will generate the following controls:

Controls generated from exposed properties and methods

API

Options

You can pass an options object for additional configuration if needed:

// .storybook/main.ts
import type { StorybookConfig } from '@storybook/vue3-vite';

const config: StorybookConfig = {
  framework: {
    name: '@storybook/vue3-vite',
    options: {
      docgen: 'vue-component-meta',
    },
  },
};

export default config;

docgen

Type: 'vue-docgen-api' | 'vue-component-meta'

Default: 'vue-docgen-api'

Choose which docgen tool to use when generating controls for your components. See Using vue-component-meta for more information.