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.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
recca0120/code-quest
آخر نشاط في المصدر
١٩ أبريل ٢٠٢٦ في ٢٢:٠٥
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
١١
التفرعات
٢

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
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
عرض على GitHub