storybook-story-writing

安装量: 295
排名: #3071

安装

npx skills add https://github.com/thebushidocollective/han --skill storybook-story-writing

Storybook - Story Writing

Write well-structured, maintainable Storybook stories using Component Story Format 3 (CSF3) that showcase component variations and ensure consistent rendering.

Key Concepts Component Story Format 3 (CSF3)

CSF3 is the modern Storybook format that uses object syntax for stories:

import type { Meta, StoryObj } from '@storybook/react'; import { Button } from './Button';

const meta = { title: 'Components/Button', component: Button, parameters: { layout: 'centered', }, tags: ['autodocs'], argTypes: { backgroundColor: { control: 'color' }, }, } satisfies Meta;

export default meta; type Story = StoryObj;

export const Primary: Story = { args: { primary: true, label: 'Button', }, };

export const Secondary: Story = { args: { label: 'Button', }, };

Story Organization One story file per component: Component.stories.tsx Use descriptive story names: Primary, Secondary, Large, Disabled Group related stories under a title hierarchy: Components/Forms/Input Default Export (Meta)

The default export defines metadata for all stories:

const meta = { title: 'Components/Button', // Navigation path component: Button, // Component reference parameters: {}, // Story-level config tags: ['autodocs'], // Enable auto-documentation argTypes: {}, // Control types decorators: [], // Wrappers for stories } satisfies Meta;

Best Practices 1. Use TypeScript for Type Safety import type { Meta, StoryObj } from '@storybook/react';

const meta = { component: Button, } satisfies Meta;

type Story = StoryObj;

  1. Show All Component States

Create stories for each meaningful state:

export const Default: Story = { args: { label: 'Click me', }, };

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

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

export const WithIcon: Story = { args: { label: 'Download', icon: 'download', }, };

  1. Use Sensible Defaults export const Primary: Story = { args: { primary: true, label: 'Button', size: 'medium', }, };

// Extend existing stories export const PrimaryLarge: Story = { ...Primary, args: { ...Primary.args, size: 'large', }, };

  1. Add Descriptive Parameters export const WithTooltip: Story = { args: { label: 'Hover me', tooltip: 'Click to submit', }, parameters: { docs: { description: { story: 'Shows a tooltip on hover to provide additional context.', }, }, }, };

  2. Use Decorators for Context import { RouterDecorator } from '../decorators';

const meta = { component: Navigation, decorators: [ (Story) => (

), RouterDecorator, ], } satisfies Meta;

Common Patterns Form Components export const EmptyForm: Story = { args: { onSubmit: (data) => console.log(data), }, };

export const PrefilledForm: Story = { args: { defaultValues: { email: 'user@example.com', name: 'John Doe', }, }, };

export const WithValidationErrors: Story = { args: { errors: { email: 'Invalid email format', name: 'Name is required', }, }, };

Layout Components export const WithSidebar: Story = { args: { sidebar: , children: , }, parameters: { layout: 'fullscreen', }, };

Data-Driven Components const mockData = [ { id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }, { id: 3, name: 'Item 3' }, ];

export const WithData: Story = { args: { items: mockData, }, };

export const Empty: Story = { args: { items: [], emptyMessage: 'No items found', }, };

Responsive Components export const Mobile: Story = { args: { variant: 'mobile', }, parameters: { viewport: { defaultViewport: 'mobile1', }, }, };

export const Desktop: Story = { args: { variant: 'desktop', }, parameters: { viewport: { defaultViewport: 'desktop', }, }, };

Anti-Patterns ❌ Don't Use Template Binding (CSF2) // Bad - Old CSF2 format const Template = (args) =>

返回排行榜