Storybook for Vue with 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.
Install
To install Storybook in an existing Vue project, run this command in your project's root directory:
npm create storybook@latestYou can then get started writing stories, running tests and documenting your components. For more control over the installation process, refer to the installation guide.
Requirements
Vue โฅ 3
Vite โฅ 5
Run Storybook
To run Storybook for a particular project, run the following:
npm run storybookTo build Storybook, run:
npm run build-storybookYou will find the output in the configured outputDir (default is storybook-static).
Configure
Storybook for Vue 3 with Vite is designed to work out of the box with minimal configuration. This section covers configuration options for the framework.
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.ts file.
Therefore, Storybook provides you with a setup function exported from this package. This function receives your Storybook instance as a callback, which you can interact with and add your custom configuration.
import { setup } from '@storybook/vue3-vite';
setup((app) => {
app.use(MyPlugin);
app.component('my-component', MyComponent);
app.mixin({
// My mixin
});
});Vapor mode
Storybook supports components that use Vapor mode, which is available from Vue 3.6. Storybook renders your stories in a regular Vue application, so you need to install Vue's vaporInteropPlugin on it with the setup function:
import { setup } from '@storybook/vue3-vite';
import { vaporInteropPlugin } from 'vue';
setup((app) => {
app.use(vaporInteropPlugin);
});Then you can mix Vapor and regular components in stories, decorators and slots. Only add this setup call if your project uses Vapor mode.
Vue's interop between Vapor and regular components covers props, events and slots, but not every edge case yet. Refer to the Vue release notes for its current limitations. We recommend using the latest version of @vitejs/plugin-vue for better interoperability.
Component documentation
Storybook 11 reads Vue component props on the server by default. To keep the Storybook 10 bundler-based docgen setup, set features.docgenServer: false. That old setup will be removed in Storybook 12.
vue-component-meta is a tool maintained by the Vue team that extracts metadata from Vue components. 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.
New projects do not need any docgen configuration. To migrate an existing project that selects vue-component-meta, remove the legacy framework option and let Storybook use the server:
import type { StorybookConfig } from '@storybook/vue3-vite';
const config: StorybookConfig = {
- framework: {
- name: '@storybook/vue3-vite',
- options: {
- docgen: 'vue-component-meta',
- },
- },
+ framework: '@storybook/vue3-vite',
};
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 describe a prop, including tags, you can use JSDoc comments in your component's props definition:
<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>The props definition above will generate the following controls:

Events types extraction
To provide a type for an emitted event, you can use TypeScript types (including JSDoc comments) in your component's defineEmits call:
<script setup lang="ts">
type MyChangeEvent = 'change';
interface MyEvents {
/** Fired when item is changed */
(event: MyChangeEvent, item?: Item): void;
/** Fired when item is deleted */
(event: 'delete', id: string): void;
/** Fired when item is upserted into list */
(e: 'upsert', id: string): void;
}
const emit = defineEmits<MyEvents>();
</script>Which will generate the following controls:

Slots types extraction
The slot types are automatically extracted from your component definition and displayed in the controls panel.
<template>
<slot :num="123"></slot>
<br />
<slot name="named" str="str"></slot>
<br />
<slot name="no-bind"></slot>
<br />
<slot name="vbind" v-bind="{ num: 123, str: 'str' }"></slot>
</template>
<script setup lang="ts"></script>If you use defineSlots, you can describe each slot using JSDoc comments in your component's slots definition:
defineSlots<{
/** Example description for default */
default(props: { num: number }): any;
/** Example description for named */
named(props: { str: string }): any;
/** Example description for no-bind */
noBind(props: {}): any;
/** Example description for vbind */
vbind(props: { num: number; str: string }): any;
}>();The definition above will generate the following controls:

Exposed properties and methods
The properties and methods exposed by your component are automatically extracted and displayed in the Controls panel.
<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:

Keep a custom vue-component-meta configuration
If you're working with a project that relies on tsconfig references to link to other existing configuration files (e.g., tsconfig.app.json, tsconfig.node.json), we recommend that you update your .storybook/main.js|ts configuration file and add the following:
import type { StorybookConfig } from '@storybook/vue3-vite';
const config: StorybookConfig = {
features: {
docgenServer: false,
},
framework: {
name: '@storybook/vue3-vite',
options: {
docgen: {
plugin: 'vue-component-meta',
tsconfig: 'tsconfig.app.json',
},
},
},
};
export default config;The server does not translate a custom docgen tsconfig. Keep docgenServer: false to continue using that builder-based configuration in Storybook 11.
This is not a limitation of Storybook, but how vue-component-meta works. For more information, refer to the appropriate GitHub issue.
Otherwise, you might face missing component types/descriptions or unresolvable import aliases like @/some/import.
FAQ
How do I manually install the Vue framework?
First, install the framework:
npm install --save-dev @storybook/vue3-viteThen, update your .storybook/main.js|ts to change the framework property:
import { defineMain } from '@storybook/vue3-vite/node';
export default defineMain({
// ...
framework: '@storybook/vue3-vite', // ๐ Add this
});Storybook doesn't work with my Vue 2 project
Vue 2 entered End of Life (EOL) on December 31st, 2023, and is no longer maintained by the Vue team. As a result, Storybook no longer supports Vue 2. We recommend you upgrade your project to Vue 3, which Storybook fully supports. If that's not an option, you can still use Storybook with Vue 2 by installing the latest version of Storybook 7 with the following command:
npx storybook@^7 initAPI
Options
You can pass an options object for additional configuration if needed:
import { defineMain } from '@storybook/vue3-vite/node';
export default defineMain({
features: {
docgenServer: false,
},
framework: {
name: '@storybook/vue3-vite',
options: {
docgen: 'vue-component-meta',
},
},
});builder
Type: Record<string, any>
Configure options for the framework's builder. For this framework, available options can be found in the Vite builder docs.
docgen
Type: 'vue-docgen-api' | 'vue-component-meta' | boolean
Default: server-side vue-component-meta. When docgenServer is off, the builder default is 'vue-docgen-api'.
Since: 8.0
Choose which builder-based docgen tool to use when generating controls for your components. This option is ignored when docgenServer is on. See Component documentation for more information.
Builder docgen is deprecated and will be removed in Storybook 12, with both 'vue-docgen-api' and 'vue-component-meta'.
Storybook warns when it runs.
Remove features.docgenServer: false and the docgen option to use the default server-side vue-component-meta implementation.
To disable docgen processing entirely in Storybook 11, turn off both the server and the builder fallback:
import type { StorybookConfig } from '@storybook/vue3-vite';
const config: StorybookConfig = {
features: {
docgenServer: false,
},
framework: {
name: '@storybook/vue3-vite',
options: {
docgen: false,
},
},
};
export default config;When to disable docgen
Disabling docgen can improve build performance for large projects, but argTypes won't be inferred automatically, which will prevent features like Controls and docs from working as expected. To use those features, you will need to define argTypes manually.
