storybook-args-controls

安装量: 57
排名: #13006

安装

npx skills add https://github.com/thebushidocollective/han --skill storybook-args-controls

Storybook - Args and Controls

Configure interactive controls and args to make stories dynamic and explorable, allowing designers and developers to test component variations in real-time.

Key Concepts Args

Args are inputs to components that Storybook tracks and makes interactive:

export const Primary: Story = { args: { label: 'Button', primary: true, size: 'medium', onClick: () => alert('clicked'), }, };

ArgTypes

ArgTypes define metadata about args, including control types and documentation:

const meta = { component: Button, argTypes: { backgroundColor: { control: 'color', description: 'Background color of the button', }, size: { control: { type: 'select' }, options: ['small', 'medium', 'large'], description: 'Size variant', }, onClick: { action: 'clicked', }, }, } satisfies Meta;

Control Types

Storybook provides various control types for different data types:

text - String input number - Number input with validation boolean - Checkbox toggle color - Color picker date - Date picker select - Dropdown menu radio - Radio buttons range - Slider with min/max object - JSON editor array - Array editor Best Practices 1. Infer Controls from TypeScript

Let Storybook auto-generate controls from TypeScript types:

interface ButtonProps { label: string; primary?: boolean; size?: 'small' | 'medium' | 'large'; backgroundColor?: string; onClick?: () => void; }

export const Button: React.FC = ({ ... }) => { ... };

const meta = { component: Button, // Controls inferred from ButtonProps } satisfies Meta;

  1. Customize Control Types When Needed

Override auto-inferred controls for better UX:

const meta = { component: ColorPicker, argTypes: { color: { control: 'color', // Override default text input }, opacity: { control: { type: 'range', min: 0, max: 1, step: 0.1 }, }, preset: { control: 'select', options: ['primary', 'secondary', 'success', 'warning', 'danger'], }, }, } satisfies Meta;

  1. Use Actions for Event Handlers

Track event callbacks in the Actions panel:

const meta = { component: Form, argTypes: { onSubmit: { action: 'submitted' }, onChange: { action: 'changed' }, onError: { action: 'error occurred' }, }, } satisfies Meta;

export const Default: Story = { args: { onSubmit: (data) => console.log('Form data:', data), }, };

  1. Set Sensible Defaults

Provide default args at the meta level:

const meta = { component: Slider, args: { min: 0, max: 100, step: 1, value: 50, }, argTypes: { value: { control: { type: 'range', min: 0, max: 100, step: 1 }, }, }, } satisfies Meta;

  1. Document Args

Add descriptions to help users understand each arg:

const meta = { component: Tooltip, argTypes: { placement: { control: 'select', options: ['top', 'right', 'bottom', 'left'], description: 'Position of the tooltip relative to its trigger', table: { defaultValue: { summary: 'top' }, type: { summary: 'string' }, }, }, delay: { control: { type: 'number', min: 0, max: 2000, step: 100 }, description: 'Delay in milliseconds before showing the tooltip', }, }, } satisfies Meta;

Common Patterns Enum/Union Type Controls type ButtonVariant = 'primary' | 'secondary' | 'danger';

const meta = { component: Button, argTypes: { variant: { control: 'radio', options: ['primary', 'secondary', 'danger'] satisfies ButtonVariant[], }, }, } satisfies Meta;

Complex Object Controls const meta = { component: Chart, argTypes: { data: { control: 'object', description: 'Chart data points', }, options: { control: 'object', description: 'Chart configuration', }, }, } satisfies Meta;

export const Default: Story = { args: { data: [ { x: 0, y: 10 }, { x: 1, y: 20 }, { x: 2, y: 15 }, ], options: { showLegend: true, animate: true, }, }, };

Conditional Controls

Hide irrelevant controls based on other arg values:

const meta = { component: Input, argTypes: { type: { control: 'select', options: ['text', 'number', 'email', 'password'], }, min: { control: 'number', if: { arg: 'type', eq: 'number' }, // Only show for number inputs }, max: { control: 'number', if: { arg: 'type', eq: 'number' }, }, showPasswordToggle: { control: 'boolean', if: { arg: 'type', eq: 'password' }, }, }, } satisfies Meta;

Disable Controls

Disable controls for props that shouldn't be editable:

const meta = { component: DataTable, argTypes: { data: { control: false, // Disable control (use args instead) }, onSort: { table: { disable: true }, // Hide from docs table }, }, } satisfies Meta;

Grouping Controls

Organize controls into logical categories:

const meta = { component: Modal, argTypes: { // Appearance title: { control: 'text', table: { category: 'Appearance' }, }, size: { control: 'select', options: ['small', 'medium', 'large'], table: { category: 'Appearance' }, },

// Behavior
closeOnEscape: {
  control: 'boolean',
  table: { category: 'Behavior' },
},
closeOnOverlayClick: {
  control: 'boolean',
  table: { category: 'Behavior' },
},

// Events
onClose: {
  action: 'closed',
  table: { category: 'Events' },
},

}, } satisfies Meta;

Advanced Patterns Custom Control Components

Create custom controls for specialized inputs:

import { useArgs } from '@storybook/preview-api';

const meta = { component: GradientPicker, argTypes: { gradient: { control: { type: 'object', }, }, }, } satisfies Meta;

export const Custom: Story = { render: (args) => { const [{ gradient }, updateArgs] = useArgs(); return ( updateArgs({ gradient: newGradient })} /> ); }, };

Dynamic ArgTypes

Generate argTypes programmatically:

const themes = ['light', 'dark', 'system'] as const;

const meta = { component: ThemeProvider, argTypes: { theme: { control: 'select', options: themes, mapping: Object.fromEntries( themes.map(theme => [theme, theme]) ), }, }, } satisfies Meta;

Anti-Patterns ❌ Don't Override Args in Render // Bad export const Example: Story = { render: (args) =>

返回排行榜