Documenting Vue Components with Storybook
AI generated
<v/>
{ }
Vue.js · Storybook · Component Library · Documentation
Documenting Vue Components
with Storybook

Component documentation that nobody reads is wasted time. Storybook makes Vue components interactively explorable, for developers, designers, and QA teams alike, generated directly from the source code.

15 min read Stories · Controls · Addons · Visual Regression · CI/CD Vue 3 · Storybook 8 · Vitest · Chromatic

1. Why document Vue components with Storybook

The biggest problem with conventional component documentation is that it drifts away from the actual code as soon as the first change is made to the component and nobody finds the time to update the docs. Vue Storybook solves this problem at its root: the documentation is code. Every story is a JavaScript function that renders the component in a specific state. When the component changes, the story automatically reflects that state, or the build breaks if the props have become incompatible.

The second advantage of Vue Storybook is decoupling from the application context. A component can be developed and tested in complete isolation in Storybook, without starting the entire application. That is especially valuable in large projects where starting the application takes minutes and navigating to the right page requires further interactions. In Storybook, the component renders immediately in exactly the state the developer wants to test.

For teams with separate designer and developer roles, Vue Storybook is the shared language. Designers can try out components in the browser, cycle through different states, test responsive breakpoints, and identify accessibility issues directly in Storybook, without access to the code or a local development environment. That significantly reduces communication overhead and makes review cycles shorter, because designers and QA work with the same instance as developers.

2. Setting up Storybook for Vue 3

Vue Storybook can be initialized into existing Vue 3 projects with a single command: npx storybook@latest init. The CLI automatically detects the framework, installs the necessary dependencies, and creates an initial configuration in the .storybook/ folder. The two most important files are main.ts, which configures Storybook, and preview.ts, which defines global decorators, parameters, and plugins that apply to all stories.

The configuration in .storybook/main.ts defines in which directories Storybook looks for story files, which addons are loaded, and which Vite configuration override Storybook uses. For Vue Storybook projects with Pinia, Vue Router, or custom provide/inject dependencies, preview.ts is where these dependencies are supplied as global decorators. A decorator is a wrapper function that embeds every story in a context, for example a Pinia store or a Vue Router context.


// .storybook/preview.ts
// Global Storybook configuration for Vue 3 with Pinia and router
import { setup } from '@storybook/vue3'
import { createPinia } from 'pinia'
import { createRouter, createMemoryHistory } from 'vue-router'
import type { Preview } from '@storybook/vue3'

// Install Pinia and Router globally for all stories
setup((app) => {
  app.use(createPinia())
  app.use(createRouter({
    history: createMemoryHistory(),
    routes: [{ path: '/:pathMatch(.*)*', component: { template: '<div/>' } }],
  }))
})

const preview: Preview = {
  parameters: {
    // Enable auto-generated docs tab from JSDoc comments and prop types
    docs: { autodocs: 'tag' },
    // Restrict responsive viewport options to standard breakpoints
    viewport: {
      viewports: {
        mobile: { name: 'Mobile', styles: { width: '375px', height: '812px' } },
        tablet: { name: 'Tablet', styles: { width: '768px', height: '1024px' } },
        desktop: { name: 'Desktop', styles: { width: '1440px', height: '900px' } },
      },
    },
    // Enable accessibility checks by default in all stories
    a11y: { config: { rules: [{ id: 'color-contrast', enabled: true }] } },
    backgrounds: {
      default: 'light',
      values: [
        { name: 'light', value: '#ffffff' },
        { name: 'dark', value: '#0f172a' },
        { name: 'slate', value: '#f8fafc' },
      ],
    },
  },
}

export default preview

3. Your first story: Component Story Format 3

Component Story Format 3 (CSF3) is the current standard for Vue Storybook stories. A story file exports a default metadata object (meta) and named exports for each story variant. The meta object defines the component, the title in the Storybook sidebar, and global args for all stories in the file. Each named export is a story that renders the component in a specific state. The reduction to a single object, without render functions or wrapper template strings, makes CSF3 stories considerably more readable than earlier formats.

In Vue Storybook, args play the central role: args are the props with which the component is rendered. Storybook automatically derives the available args from the TypeScript types or the defined defineProps declarations of the Vue component. That means no separate documentation of the props is necessary, Storybook generates the controls UI directly from the component code. JSDoc comments on the props appear as description text in the controls table.

4. Controls: making props interactively explorable

Controls are the most interactive feature of Vue Storybook. Every prop of a Vue component automatically gets a matching control widget in the Storybook UI: boolean props get a toggle, string props get a text field, string unions get a select dropdown, number props get a slider or a number field. This lets developers, designers, and testers explore the component directly in the browser in various states, without having to change code. A button component can be clicked through interactively in all its variants, primary, secondary, disabled, loading.

For more complex props such as arrays or objects, the controls configuration can be customized in the argTypes section of the story metadata. There you can explicitly set the control type, restrict the range for numeric controls, and define options for select controls. For Vue Storybook projects with a design token library, it is worth capturing color values as control options, so designers can test the component with the actual token vocabulary instead of entering hexadecimal colors.


// src/components/Button/Button.stories.ts
// CSF3 story file for the Button component with controls and variants
import type { Meta, StoryObj } from '@storybook/vue3'
import Button from './Button.vue'

// Meta defines component and global defaults for all stories in this file
const meta: Meta<typeof Button> = {
  title: 'UI/Button',
  component: Button,
  tags: ['autodocs'],  // Auto-generate a Docs page from props and JSDoc
  argTypes: {
    variant: {
      control: 'select',
      options: ['primary', 'secondary', 'ghost', 'danger'],
      description: 'Visual style variant of the button',
    },
    size: {
      control: 'radio',
      options: ['sm', 'md', 'lg'],
    },
    onClick: { action: 'clicked' },  // Log click events in Actions panel
  },
  args: {
    // Default args shared by all stories in this file
    label: 'Button Label',
    variant: 'primary',
    size: 'md',
    disabled: false,
    loading: false,
  },
}

export default meta
type Story = StoryObj<typeof meta>

// Each named export is one story, rendered with the given args
export const Primary: Story = {}

export const Secondary: Story = {
  args: { variant: 'secondary' },
}

export const Loading: Story = {
  args: { loading: true, label: 'Loading...' },
}

export const Disabled: Story = {
  args: { disabled: true },
}

// Story with render function for complex template scenarios
export const WithIcon: Story = {
  render: (args) => ({
    components: { Button },
    setup() { return { args } },
    template: `<Button v-bind="args"><template #icon>★</template></Button>`,
  }),
}

5. Addons: accessibility, viewport, and docs

The real value of Vue Storybook unfolds through the addon ecosystem. The accessibility addon (@storybook/addon-a11y) automatically runs axe checks on every story and shows accessibility violations directly in the Storybook panel. That is especially valuable for design systems: every new component is automatically checked for WCAG conformance, without a separate test infrastructure. Contrast ratio errors, missing ARIA labels, and incorrect heading hierarchies are made visible immediately.

The docs addon automatically generates a structured documentation page for each component from stories, JSDoc comments, and TypeScript prop types. This page contains an interactive props table, an overview of all story variants, and manually written MDX content if desired. The result is Vue Storybook documentation that is always in sync with the current code and requires no separate maintenance effort. The viewport addon makes it easy to test components at different screen widths, without opening browser devtools.

6. Testing composables and state in stories

A common challenge in Vue Storybook projects is testing components that rely on composables with external state, API calls, Pinia stores, or global context values. The cleanest solution is mocking at the story level: instead of executing the real API call, the story registers a mock handler that returns the expected response. The Mock Service Worker addon (msw-storybook-addon) integrates MSW directly into Storybook, so API calls are intercepted at the network layer, exactly as in real tests, without changing the production code.

For Pinia stores in Vue Storybook, a story-level decorator is the most elegant solution. The decorator creates a fresh Pinia store, populates it with the state relevant to the story, and supplies it to the component via provide. This allows documenting components in a logged-in state, an error state, or an empty state, without rebuilding the store logic in the story. Every story shows exactly the state it is meant to communicate, fully reproducible, at any time.

7. Visual regression tests with Chromatic

Visual regression tests are especially easy to implement in Vue Storybook projects with Chromatic. Chromatic is a cloud service that performs screenshot comparisons of all stories on every commit and alerts developers to visual changes. The difference to other visual testing solutions: Chromatic uses Storybook directly as a test suite. No separate test configuration, no browser control via Puppeteer, the stories that already exist become the complete visual test catalog.

The workflow in a Vue Storybook project with Chromatic is: the developer pushes, CI builds Storybook, Chromatic compares all stories against the current baseline screenshot and flags changes. The developer reviews the flagged diffs in the Chromatic dashboard and accepts intended changes or rejects unintended ones. Accepted changes become the new baseline. This workflow prevents accidental visual regressions, which frequently occur in large component libraries when changes to shared styles have unexpected effects.

8. Integrating Storybook into CI/CD pipelines

Integrating Vue Storybook into CI/CD pipelines has three essential components: the Storybook build check, optional visual regression tests, and deploying the static Storybook as a review environment. The Storybook build (storybook build) fails if components have TypeScript errors or stories cannot render. That makes the build an effective quality gate: stories that reference broken props or have broken imports block the merge.

Deploying the static Storybook as part of the CI process gives the entire team, developers, designers, QA, product owners, an always up to date view of all components in all documented states. Services such as Chromatic, Netlify, or GitHub Pages can publish a static Storybook directly from the CI artifact. A link in the pull request description to the current Storybook instance of the branch makes code reviews more efficient, because reviewers can judge visual changes directly in the browser, without setting up local development environments.

9. Documentation approaches compared

For Vue Storybook, the comparison with other documentation approaches is instructive, not to sell Storybook, but to choose the right approach for the right context.

Approach Freshness Interactivity Suited for
Storybook Automatically current Fully interactive Component libraries, design systems
VuePress / VitePress Manually maintained Embedded demos possible API docs, guides, tutorials
README.md Often outdated No interactivity Short overviews, setup instructions
Figma tokens Current on the design side Design tool interactivity Design-to-code workflow
Inline JSDoc Automatically current No interactivity IDE autocompletion

In practice, Vue Storybook and VitePress complement each other best: Storybook for interactive component documentation, VitePress for overarching concepts, design decisions, and API documentation. Both can be generated from the same source components and JSDoc comments, but address different audiences, Storybook primarily developers and designers in the daily workflow, VitePress for external users of the library or new team members.

Mironsoft

Vue Component Library · Storybook · Design System Setup

Building a Vue component library with Storybook?

We design and implement Vue component libraries with complete Storybook documentation, visual regression tests, and CI/CD integration.

Design System

Designing component architecture, defining tokens, and setting up Storybook

Stories & Controls

Writing CSF3 stories for all component states and configuring controls

CI & Visual Tests

Chromatic integration, Storybook build as a quality gate, and automated deployment

10. Summary

Vue Storybook is more than a documentation tool, it is a development environment for components in isolation. Stories in CSF3 are maintainable code, not documentation prose that goes stale. Controls make props interactive and give designers direct access to component states. The accessibility addon makes WCAG checks a standard workflow. Visual regression tests with Chromatic prevent unintended visual regressions. The Storybook build as a CI gate ensures that broken components do not slip unnoticed into the main branch.

The most important factor for a successful Vue Storybook project is the discipline of writing stories alongside component development, not afterward as a separate task. When Storybook is part of the workflow from the start, stories become living documentation that the team uses and keeps current on a daily basis. Storybook then automatically flags it when someone breaks a component, and that is the greatest value of the entire system.

Vue Storybook: The Essentials at a Glance

CSF3 Stories

Component Story Format 3: named exports for each story variant, automatic controls from TypeScript props, no render template boilerplate.

Addons

a11y for accessibility checks, viewport for responsive tests, docs for auto-generated documentation from JSDoc and prop types.

Visual Regression

Chromatic compares stories on every commit. Stories become the complete visual test catalog without a separate test configuration.

CI/CD

Storybook build as a quality gate, fails on TypeScript errors and broken stories. Static deployment for team-wide review links.

11. FAQ: Documenting Vue Components with Storybook

1Story vs. unit test?
A story visualizes component states for humans. A unit test checks logic programmatically. Both complement each other, stories as the basis for visual regression, Vitest for logic.
2Pinia store in Storybook?
Initialize Pinia globally in preview.ts via setup(). Set story state in a beforeEach decorator or a render function.
3Storybook in a monorepo for Vue and React?
Yes, separate Storybook instances per package. Extract shared decorators as their own package.
4Is Chromatic usable for free?
Free tier with 5,000 snapshots/month. Sufficient for small teams. Alternatives: Percy, Playwright snapshots.
5Documenting slots in Storybook?
Via a render function with a template string. Alternatively @storybook/addon-slots for automatic slot controls.
6Storybook packages in the production bundle?
Storybook packages in devDependencies, not in the production bundle. Vite ignores devDependencies automatically.
7Integrating Tailwind into Storybook?
Import the Tailwind CSS file in preview.ts. Storybook uses Vite plus PostCSS just like the main project.
8What does autodocs do?
Generates a docs page with a props table, descriptions, and all stories as interactive examples. Recommended for every public library component.
9Storybook for internal business applications?
Yes, prevents component duplication, makes designer and QA reviews more efficient, and serves as living documentation for the team.
10CSS custom properties in Storybook?
Import global styles and tokens in preview.ts. Must be defined in :root scope, Storybook renders in its own iframe, tokens must be reachable there.