React Storybook: Isolate React Component Development with Hot Reloading.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Global and local component wrapper system for consistent styling and context provision across stories. Decorators provide a way to wrap components with additional functionality or styling without modifying the components themselves.
Adds a global decorator that will be applied to all stories across the entire Storybook instance.
/**
* Adds a global decorator to all stories
* @param decorator - Function that wraps story components
*/
function addDecorator(decorator: StoryDecorator): void;Usage Examples:
import { addDecorator, clearDecorators } from '@kadira/storybook';
// Basic wrapper decorator
addDecorator((storyFn, context) => (
<div style={{ padding: '20px', backgroundColor: '#f5f5f5' }}>
{storyFn()}
</div>
));
// Theme provider decorator
import { ThemeProvider } from 'styled-components';
import theme from '../src/theme';
addDecorator((storyFn) => (
<ThemeProvider theme={theme}>
{storyFn()}
</ThemeProvider>
));
// Context-aware decorator using story information
addDecorator((storyFn, context) => {
const isDarkTheme = context.story.includes('dark');
return (
<div className={isDarkTheme ? 'dark-theme' : 'light-theme'}>
<h3>Story: {context.kind} - {context.story}</h3>
{storyFn()}
</div>
);
});Removes all global decorators that have been added to the Storybook instance. This is useful for hot module replacement and testing scenarios.
/**
* Removes all global decorators from the Storybook instance
*/
function clearDecorators(): void;Usage Examples:
import { clearDecorators, addDecorator } from '@kadira/storybook';
// Clear all existing decorators
clearDecorators();
// Add fresh decorators
addDecorator((storyFn) => (
<div className="fresh-decorator">
{storyFn()}
</div>
));
// Used internally for hot module replacement
if (module.hot) {
module.hot.dispose(() => {
clearDecorators();
});
}Individual story collections can have their own decorators that apply only to stories within that collection.
/**
* Adds a decorator to all stories in this collection
* @param decorator - Function that wraps story components
* @returns Story object for method chaining
*/
Story.addDecorator(decorator: StoryDecorator): Story;Usage Examples:
import { storiesOf } from '@kadira/storybook';
// Decorator for specific story collection
storiesOf('Form Components', module)
.addDecorator((storyFn) => (
<form style={{ padding: '20px' }}>
{storyFn()}
</form>
))
.add('text input', () => <input type="text" />)
.add('checkbox', () => <input type="checkbox" />);
// Multiple decorators on same collection
storiesOf('Card Components', module)
.addDecorator((storyFn) => (
<div className="container">
{storyFn()}
</div>
))
.addDecorator((storyFn) => (
<div style={{ maxWidth: '400px', margin: 'auto' }}>
{storyFn()}
</div>
))
.add('basic card', () => <Card title="Example" />);Examples of frequently used decorator patterns for different use cases.
Layout Decorators:
// Center content decorator
const CenterDecorator = (storyFn) => (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100vh'
}}>
{storyFn()}
</div>
);
// Grid layout decorator
const GridDecorator = (storyFn) => (
<div style={{
display: 'grid',
gap: '20px',
padding: '20px',
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))'
}}>
{storyFn()}
</div>
);Context Decorators:
// Router decorator for components needing routing context
import { BrowserRouter } from 'react-router-dom';
const RouterDecorator = (storyFn) => (
<BrowserRouter>
{storyFn()}
</BrowserRouter>
);
// Redux store decorator
import { Provider } from 'react-redux';
import store from '../src/store';
const ReduxDecorator = (storyFn) => (
<Provider store={store}>
{storyFn()}
</Provider>
);Information Decorators:
// Story info decorator showing component details
const InfoDecorator = (storyFn, context) => (
<div>
<div style={{
padding: '10px',
backgroundColor: '#f0f0f0',
marginBottom: '20px'
}}>
<strong>Component:</strong> {context.kind} <br/>
<strong>Story:</strong> {context.story}
</div>
{storyFn()}
</div>
);interface StoryDecorator {
/**
* Decorator function that wraps story components
* @param story - Function that returns the story component
* @param context - Story context information
* @returns JSX element wrapping the story
*/
(story: Function, context: StoryContext): Object;
}
interface StoryContext {
/** The story collection name */
kind: string;
/** The individual story name */
story: string;
}