Storybook Guide — Component Development and Documentation
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
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
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.
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.
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.
Ignoring accessibility violations: The a11y addon reports real issues. Don’t disable it or dismiss violations. Fix the underlying accessibility problem.
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
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).
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.
What problem do decorators solve? Answer: Decorators wrap stories with shared context (theme, routing, providers, layout) without duplicating code across every story file.
How do interaction tests run? Answer: The
playfunction runs after the story renders. It usesuserEventto simulate real browser interactions andexpectto 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
Try It Yourself
npx storybook@latest init --type react
cd src/stories
# Explore the existing Button, Header, and Page stories
npm run storybookOpen 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
| Topic | Description |
|---|---|
| Complement Storybook with unit tests | |
| 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