Skip to content
Storybook Guide — Component Development and Documentation

Storybook Guide — Component Development and Documentation

DodaTech Updated Jun 7, 2026 7 min read

Storybook is a frontend workshop that lets you build, test, and document UI components in isolation — outside your application — with interactive controls, visual regression testing, and auto-generated documentation that stays in sync with your code.

What You’ll Learn

  • Setting up Storybook with React and TypeScript
  • Writing stories with args, parameters, and decorators
  • Using addons for Controls, Actions, Docs, and Accessibility
  • Testing components with interaction tests
  • Organizing stories with tags and naming conventions

Why Storybook Matters

Building UI components inside your app forces you to navigate pages, fill forms, and set up state just to see a single button variant. Storybook isolates each component so you can develop every state — loading, empty, error, hover, focus, disabled — without touching your app. This makes UI development faster, more thorough, and more collaborative because designers can review components without running the full application. Doda Browser uses Storybook to document its UI component library — every button, modal, and input field has a story showing all its states and variants.

    flowchart LR
    A[JavaScript & React Basics] --> B[Storybook]
    B --> C[Stories]
    B --> D[Args & Controls]
    B --> E[Addons]
    B --> F[Testing]
    C --> G[Component States]
    D --> H[Interactive Props]
    E --> I[Accessibility, Docs, Actions]
    style B fill:#ff4785,color:#fff
  
Prerequisites: Solid JavaScript and React knowledge. Experience with TypeScript is helpful but not required.

Core Concepts

Setup and First Story

# Add Storybook to an existing project
npx storybook@latest init --type react

# Output:
# ✔ Installing dependencies
# ✔ Adding stories to src/stories/
# Storybook started at http://localhost:6006
// src/components/Button.tsx
import React from "react";

interface ButtonProps {
  label: string;
  variant?: "primary" | "secondary";
  disabled?: boolean;
  onClick?: () => void;
}

export function Button({ label, variant = "primary", disabled = false }: ButtonProps) {
  return (
    <button
      className={`btn btn-${variant}`}
      disabled={disabled}
    >
      {label}
    </button>
  );
}
// src/stories/Button.stories.tsx
import type { Meta, StoryObj } from "@storybook/react";
import { Button } from "../components/Button";

const meta = {
  title: "Components/Button",
  component: Button,
  tags: ["autodocs"],
  argTypes: {
    variant: {
      control: "select",
      options: ["primary", "secondary"],
    },
  },
} satisfies Meta<typeof Button>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Primary: Story = {
  args: {
    label: "Click Me",
    variant: "primary",
  },
};

export const Secondary: Story = {
  args: {
    label: "Cancel",
    variant: "secondary",
  },
};

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

Output: Storybook displays three stories for the Button component — Primary, Secondary, and Disabled — each with editable controls for label, variant, and disabled. The Controls panel lets you change props interactively without editing code.

Args — Component Parameters

Args are the props passed to your component in each story:

export const LongLabel: Story = {
  args: {
    label: "This is a very long button label that might overflow",
    variant: "primary",
  },
};

// Args composition — reuse args from another story
export const SecondaryDisabled: Story = {
  args: {
    ...Secondary.args,
    disabled: true,
  },
};

Output: Each story can define its own args, combine args from other stories, and override individual values. The Controls panel always reflects the current args, so you can experiment with values beyond the defined stories.

Decorators — Wrapping Components

Decorators wrap your story in a layout, context provider, or theme provider:

// .storybook/preview.js
export const decorators = [
  (Story) => (
    <div style={{ padding: "20px", backgroundColor: "#f5f5f5" }}>
      <Story />
    </div>
  ),
];

// Per-story decorators
export const WithPadding: Story = {
  decorators: [
    (Story) => (
      <div style={{ margin: "40px" }}>
        <Story />
      </div>
    ),
  ],
};

Output: All stories render inside the global decorator (gray background, padding). The WithPadding story adds extra margin on top. Decorators are useful for providers (ThemeProvider, Router), layouts, and mocked contexts.

Essential Addons

npm install -D @storybook/addon-a11y @storybook/addon-interactions
// .storybook/main.js
export default {
  addons: [
    "@storybook/addon-controls",      // Interactive prop controls
    "@storybook/addon-actions",       // Event logging (clicks, inputs)
    "@storybook/addon-docs",          // Auto-generated documentation
    "@storybook/addon-a11y",          // Accessibility checks
    "@storybook/addon-interactions",  // Interaction testing
  ],
};

Accessibility (a11y) addon catches violations automatically:

// The a11y addon runs on every story
// It reports issues like:
// - Buttons must have discernible text
// - Images must have alt text
// - Color contrast ratios

export const ButtonWithA11y: Story = {
  args: { label: "Accessible Button" },
  parameters: {
    a11y: {
      config: { rules: [{ id: "button-name", enabled: true }] },
    },
  },
};

Actions addon logs events:

export const WithClick: Story = {
  args: {
    label: "Click me",
    onClick: () => console.log("Button clicked"), // Actions shows this in a panel
  },
  parameters: {
    actions: { argTypesRegex: "^on.*" }, // Auto-capture all onClick, onChange, etc.
  },
};

Testing with Interactions

import { userEvent, within, expect } from "@storybook/test";

export const InteractionTest: Story = {
  args: { label: "Submit" },
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);

    // Find the button
    const button = canvas.getByRole("button", { name: /submit/i });

    // Click it
    await userEvent.click(button);

    // Verify state after click
    expect(button).toHaveClass("btn-primary");
    expect(button).not.toBeDisabled();
  },
};

Output: Storybook runs the play function after rendering the story. It simulates a user clicking the button and asserts the expected behavior. These tests run in the browser and can catch runtime errors.

Common Mistakes

  1. Writing stories that depend on external data (API calls): Stories should be self-contained. Mock API calls with MSW (Mock Service Worker) or pass mock data directly as props.

  2. Not testing error/empty states: Most developers test the “happy path” only. Stories should include loading, empty, error, and edge case variants for every component.

  3. Overusing decorators for simple components: A decorator that wraps every story in a full app layout slows down Storybook. Use decorators sparingly — prefer inline wrappers in specific stories.

  4. Ignoring accessibility violations: The a11y addon reports real issues. Don’t disable it or dismiss violations. Fix the underlying accessibility problem.

  5. Storing secrets or sensitive data in story args: Stories are part of your codebase and may be deployed to a public Storybook site. Never include API keys, tokens, or passwords.

Practice Questions

  1. What is the purpose of a Storybook story? Answer: A story captures a rendered state of a component with specific props. Each story represents one variant (primary button, disabled button, loading state).

  2. How do Controls differ from Args? Answer: Args define the initial props for a story. Controls are the interactive UI that lets you change those props in the Storybook panel to experiment with different values.

  3. What problem do decorators solve? Answer: Decorators wrap stories with shared context (theme, routing, providers, layout) without duplicating code across every story file.

  4. How do interaction tests run? Answer: The play function runs after the story renders. It uses userEvent to simulate real browser interactions and expect to verify the results.

Challenge

Build a component library with Storybook: create Button, Modal, TextInput, and Select components with TypeScript, write stories for every variant (including disabled, error, loading, empty), add Controls and Actions addons, include a11y checks, write interaction tests for form submission, and auto-generate documentation with the Docs addon.

FAQ

Do I need Storybook for my project?
: If your project has more than 5-10 reusable UI components, Storybook pays for itself in developer time. For simple projects, it may be overkill.
Can I use Storybook with frameworks other than React?
: Yes. Storybook supports React, Vue, Angular, Svelte, Solid, and many others through framework-specific addons.
How does Storybook handle CSS?
: Storybook imports your CSS normally. For CSS-in-JS (styled-components, Emotion), configure the addon for proper rendering.
Can I deploy Storybook as a documentation site?
: Yes. Build with npm run build-storybook and deploy the storybook-static/ folder to any static host.
Does Storybook support visual regression testing?
: Yes, through Chromatic (paid) or the @storybook/addon-storyshots addon for snapshot testing.

Try It Yourself

npx storybook@latest init --type react
cd src/stories
# Explore the existing Button, Header, and Page stories
npm run storybook

Open http://localhost:6006, click on the Button story, try the Controls panel to change the label, check the Actions tab after clicking the button, and observe accessibility violations in the a11y panel.

What’s Next

TopicDescription
React Testing Library
Complement Storybook with unit tests
React
Build the components you’ll document

Related topics: JavaScript, React, TypeScript, CSS, HTML

What’s Next

Congratulations on completing this Storybook tutorial! Here’s where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Apply what you learned by building something real
  • Explore related topics — Check out other tutorials in the same category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro