This guide provides instructions for migrating React components to Storybook 10 in the Superdesk UI Framework.
Storybook is now integrated into this project to provide interactive component documentation and development environment. This guide explains how to create stories for components following the established patterns.
# Development mode (hot reload)
npm run storybook
# Build static version
npm run build-storybookStorybook will run at http://localhost:6006/
Place story files alongside component files in app-typescript/components/:
app-typescript/components/
Button.tsx # Component implementation
Button.stories.tsx # Component stories
Here's a template for creating component stories using CSF 3.0 (Component Story Format):
import React from 'react';
import type {Meta, StoryObj} from '@storybook/react';
import {YourComponent} from './YourComponent';
const meta = {
title: 'Components/YourComponent',
component: YourComponent,
parameters: {
layout: 'centered',
docs: {
description: {
component: 'A brief description of your component and its purpose.',
},
},
},
tags: ['autodocs'],
argTypes: {
propName: {
control: 'text',
description: 'Description of what this prop does',
table: {
defaultValue: {summary: 'default'},
},
},
// Add argTypes for all props
},
} satisfies Meta<typeof YourComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
// 1. Playground - Interactive exploration
export const Playground: Story = {
args: {
// Default prop values
},
};
// 2. Additional example stories
export const Example: Story = {
args: {
// Specific configuration
},
};Every component should have a Playground story for interactive exploration:
export const Playground: Story = {
args: {
text: 'Button Text',
type: 'primary',
onClick: () => console.info('Button clicked'),
},
};Show different variants of the component:
export const Variants: Story = {
render: () => (
<div style={{display: 'flex', gap: '12px', flexWrap: 'wrap'}}>
<YourComponent variant="primary" text="Primary" />
<YourComponent variant="secondary" text="Secondary" />
<YourComponent variant="tertiary" text="Tertiary" />
</div>
),
parameters: {
controls: {disable: true},
docs: {
description: {
story: 'Available variants of the component.',
},
},
},
};Demonstrate different states (disabled, loading, error, etc.):
export const States: Story = {
render: () => (
<div style={{display: 'flex', gap: '12px', flexWrap: 'wrap'}}>
<YourComponent state="normal" />
<YourComponent state="disabled" disabled />
<YourComponent state="loading" isLoading />
</div>
),
parameters: {
controls: {disable: true},
},
};Storybook provides various control types for props:
argTypes: {
// Text input
text: {
control: 'text',
description: 'Text content',
},
// Boolean toggle
disabled: {
control: 'boolean',
description: 'Disable interactions',
},
// Select dropdown
size: {
control: 'select',
options: ['small', 'medium', 'large'],
description: 'Component size',
},
// Number input
count: {
control: 'number',
description: 'Item count',
},
// Color picker
color: {
control: 'color',
description: 'Background color',
},
// Action handler
onClick: {
action: 'clicked',
description: 'Click handler function',
},
}Specify default values in the table:
propName: {
control: 'select',
options: ['option1', 'option2'],
table: {
defaultValue: {summary: 'option1'},
},
}Always provide a clear component description:
parameters: {
docs: {
description: {
component: 'Clear, concise description of what the component does and when to use it.',
},
},
}Add context to individual stories:
export const Example: Story = {
args: {...},
parameters: {
docs: {
description: {
story: 'Explain what this specific story demonstrates.',
},
},
},
};Document all props with clear descriptions:
argTypes: {
propName: {
control: 'text',
description: 'Clear description of what this prop does and its expected values',
},
}Use the built-in Accessibility addon to verify:
- Color contrast ratios meet WCAG AA standards
- ARIA attributes are correct
- Keyboard navigation works properly
- Screen reader compatibility
Test components at different viewport sizes using the Viewport addon.
See app-typescript/components/Button.stories.tsx for a complete reference implementation featuring:
- Comprehensive argTypes for all 15+ props
- Interactive Playground story
- Variant demonstrations (Primary, Secondary, Tertiary)
- Size variations (Small, Normal, Large)
- State examples (Normal, Disabled, Loading)
- Icon usage patterns
.storybook/main.ts- Main configuration, addons, webpack customization.storybook/preview.ts- Global decorators, parameters, and styles
- Autodocs: Automatic documentation generation from TypeScript types
- SCSS Support: Full support for existing styles via webpack config
- TypeScript: Full type safety with react-docgen-typescript
- Accessibility: Built-in a11y testing
- Responsive: Viewport testing for different screen sizes
If you see ReferenceError: React is not defined in Storybook:
Cause: Story file uses JSX but doesn't import React.
Fix: Add import React from 'react'; at the top of your story file:
import React from 'react';
import type {Meta, StoryObj} from '@storybook/react';Why: React 16 requires explicit React import for JSX (unlike React 17+ with automatic JSX runtime).
Ensure SCSS files are imported in .storybook/preview.ts:
import '../app/styles/app.scss';If TypeScript errors occur, check:
- Component exports are correctly named
- Props interface is exported
- Types are properly defined
Verify:
- File matches the pattern in
.storybook/main.ts:app-typescript/**/*.stories.@(ts|tsx) - File exports a default meta object
- File exports at least one story
- Storybook dev server has been restarted
When migrating a component to Storybook:
- Create
.stories.tsxfile alongside component - Import React: Add
import React from 'react';at the top (required for JSX) - Import component and Storybook types
- Define meta object with title, component, and parameters
- Add comprehensive argTypes for all props
- Enable autodocs with
tags: ['autodocs'] - Create Playground story with interactive controls
- Add variant/example stories as needed
- Test all stories render correctly
- Verify accessibility with a11y addon
- Test responsive behavior
- Document any special usage notes