Skip to main content

storybook-component

Component-driven development with Storybook 10. Use when creating or documenting React components, writing stories or interaction tests, designing UI variations, or syncing stories after component changes.

Aller à l'installation

Informations de source

Dépôt
recca0120/code-quest
Dernière activité de la source
19 avril 2026 à 22:05
Langue détectée de SKILL.md
anglais
Étoiles
11
Forks
2

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
storybook-component
description
Component-driven development with Storybook 10. Use when creating or documenting React components, writing stories or interaction tests, designing UI variations, or syncing stories after component changes.
# Storybook 10 Component Development ## Philosophy Components are designed in Storybook first, then integrated into the app. Every component gets a `.stories.tsx` file co-located next to it. ``` components/ ChatMessage.tsx ChatMessage.stories.tsx ChatInput.tsx ChatInput.stories.tsx ``` ## Story File Template (CSF3) ```tsx import type { Meta, StoryObj } from '@storybook/react-vite'; import { fn } from 'storybook/test'; import { MyComponent } from './MyComponent'; const meta = { component: MyComponent, tags: ['autodocs'], // Decorators use design token classes, NEVER inline style with hex decorators: [ (Story) => ( <div className="bg-bg text-text p-4"> <Story /> </div> ), ], // Default args shared across all stories args: { onClick: fn(), }, } satisfies Meta<typeof MyComponent>; export default meta; type Story = StoryObj<typeof meta>; ``` ## Writing Stories — One Story Per State Each named export = one visual state. Cover: default, edge cases, loading, error, disabled. ```tsx export const Default: Story = { args: { label: 'Click me', variant: 'primary', }, }; export const Disabled: Story = { args: { ...Default.args, disabled: true, }, }; export const LongContent: Story = { args: { label: 'A very long label that might overflow the button container', }, }; export const Empty: Story = { args: { label: '', }, }; ``` ## Interaction Testing with Play Functions Use play functions to verify interactive behavior directly in Storybook. This replaces basic render tests — no need to duplicate in vitest. ```tsx import { expect, fn, within, userEvent } from 'storybook/test'; export const SubmitForm: Story = { args: { onSubmit: fn(), }, play: async ({ args, canvas, userEvent, step }) => { await step('Fill in form', async () => { await userEvent.type(canvas.getByLabelText('Email'), 'test@example.com'); await userEvent.type(canvas.getByLabelText('Password'), 'secret123'); }); await step('Submit', async () => { await userEvent.click(canvas.getByRole('button', { name: 'Submit' })); }); await expect(args.onSubmit).toHaveBeenCalledOnce(); }, }; ``` ### Key APIs | API | Usage | |-----|-------| | `canvas.getByRole()` | Preferred — query by accessibility role | | `canvas.getByLabelText()` | Form fields with labels | | `canvas.getByText()` | Visible text content | | `canvas.findByRole()` | Async — waits for element to appear | | `canvas.queryByRole()` | Check element absence (returns null) | | `userEvent.click()` | Click interaction | | `userEvent.type()` | Type into input | | `userEvent.hover()` | Hover over element | | `expect()` | Jest-compatible assertions | | `fn()` | Create spy for callback args | | `step()` | Group interactions with labels | ## Custom Render When the component needs siblings or wrapper context: ```tsx export const WithAlert: Story = { args: { message: 'Hello' }, render: (args) => ( <div className="chat-container"> <MyComponent {...args} /> <footer>Status: connected</footer> </div> ), }; ``` ## Decorators for Providers Wrap stories with context providers at the meta level: ```tsx const meta = { component: ChatPanel, decorators: [ (Story) => ( <SocketProvider value={mockSocket}> <Story /> </SocketProvider> ), ], } satisfies Meta<typeof ChatPanel>; ``` ## Parameters for Addon Config ```tsx export const DarkMode: Story = { parameters: { backgrounds: { default: 'dark' }, layout: 'fullscreen', // or 'centered', 'padded' }, }; ``` ## Testing Strategy Split | What to test | Where | |-------------|-------| | Visual states & variations | Storybook stories (args) | | User interactions & UI behavior | Storybook play functions | | Business logic, hooks, stores | Vitest unit tests | | Complex async flows | Vitest with mocks | **Rule**: If it's about how the component *looks* or *responds to clicks*, put it in Storybook. If it's about *logic*, put it in vitest. ## Storybook Config (React + Vite) Storybook 10 has essentials and interactions built-in. Only add extra addons as needed. ```ts // .storybook/main.ts import type { StorybookConfig } from '@storybook/react-vite'; const config: StorybookConfig = { stories: ['../src/**/*.stories.@(ts|tsx)'], framework: '@storybook/react-vite', addons: ['@storybook/addon-a11y'], }; export default config; ``` ```ts // .storybook/preview.ts import type { Preview } from '@storybook/react-vite'; const preview: Preview = { parameters: { layout: 'centered', }, }; export default preview; ``` ## Naming Conventions - File: `ComponentName.stories.tsx` (co-located with component) - Meta title: auto-derived from file path, or explicit `title: 'Components/ChatMessage'` - Story names: PascalCase describing the state: `Default`, `Loading`, `WithError`, `LongContent` ## Checklist for New Components 1. Create component file with props interface 2. Create `.stories.tsx` with meta + Default story 3. Add story variants for each meaningful state 4. Add play functions for interactive behavior 5. Verify in Storybook UI (`pnpm storybook`) 6. Add vitest tests only for logic not covered by stories
Voir sur GitHub