0
# Decorators
1
2
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.
3
4
## Capabilities
5
6
### Add Decorator
7
8
Adds a global decorator that will be applied to all stories across the entire Storybook instance.
9
10
```javascript { .api }
11
/**
12
* Adds a global decorator to all stories
13
* @param decorator - Function that wraps story components
14
*/
15
function addDecorator(decorator: StoryDecorator): void;
16
```
17
18
**Usage Examples:**
19
20
```javascript
21
import { addDecorator, clearDecorators } from '@kadira/storybook';
22
23
// Basic wrapper decorator
24
addDecorator((storyFn, context) => (
25
<div style={{ padding: '20px', backgroundColor: '#f5f5f5' }}>
26
{storyFn()}
27
</div>
28
));
29
30
// Theme provider decorator
31
import { ThemeProvider } from 'styled-components';
32
import theme from '../src/theme';
33
34
addDecorator((storyFn) => (
35
<ThemeProvider theme={theme}>
36
{storyFn()}
37
</ThemeProvider>
38
));
39
40
// Context-aware decorator using story information
41
addDecorator((storyFn, context) => {
42
const isDarkTheme = context.story.includes('dark');
43
return (
44
<div className={isDarkTheme ? 'dark-theme' : 'light-theme'}>
45
<h3>Story: {context.kind} - {context.story}</h3>
46
{storyFn()}
47
</div>
48
);
49
});
50
```
51
52
### Clear Decorators
53
54
Removes all global decorators that have been added to the Storybook instance. This is useful for hot module replacement and testing scenarios.
55
56
```javascript { .api }
57
/**
58
* Removes all global decorators from the Storybook instance
59
*/
60
function clearDecorators(): void;
61
```
62
63
**Usage Examples:**
64
65
```javascript
66
import { clearDecorators, addDecorator } from '@kadira/storybook';
67
68
// Clear all existing decorators
69
clearDecorators();
70
71
// Add fresh decorators
72
addDecorator((storyFn) => (
73
<div className="fresh-decorator">
74
{storyFn()}
75
</div>
76
));
77
78
// Used internally for hot module replacement
79
if (module.hot) {
80
module.hot.dispose(() => {
81
clearDecorators();
82
});
83
}
84
```
85
86
### Story-Level Decorators
87
88
Individual story collections can have their own decorators that apply only to stories within that collection.
89
90
```javascript { .api }
91
/**
92
* Adds a decorator to all stories in this collection
93
* @param decorator - Function that wraps story components
94
* @returns Story object for method chaining
95
*/
96
Story.addDecorator(decorator: StoryDecorator): Story;
97
```
98
99
**Usage Examples:**
100
101
```javascript
102
import { storiesOf } from '@kadira/storybook';
103
104
// Decorator for specific story collection
105
storiesOf('Form Components', module)
106
.addDecorator((storyFn) => (
107
<form style={{ padding: '20px' }}>
108
{storyFn()}
109
</form>
110
))
111
.add('text input', () => <input type="text" />)
112
.add('checkbox', () => <input type="checkbox" />);
113
114
// Multiple decorators on same collection
115
storiesOf('Card Components', module)
116
.addDecorator((storyFn) => (
117
<div className="container">
118
{storyFn()}
119
</div>
120
))
121
.addDecorator((storyFn) => (
122
<div style={{ maxWidth: '400px', margin: 'auto' }}>
123
{storyFn()}
124
</div>
125
))
126
.add('basic card', () => <Card title="Example" />);
127
```
128
129
### Common Decorator Patterns
130
131
Examples of frequently used decorator patterns for different use cases.
132
133
**Layout Decorators:**
134
135
```javascript
136
// Center content decorator
137
const CenterDecorator = (storyFn) => (
138
<div style={{
139
display: 'flex',
140
justifyContent: 'center',
141
alignItems: 'center',
142
height: '100vh'
143
}}>
144
{storyFn()}
145
</div>
146
);
147
148
// Grid layout decorator
149
const GridDecorator = (storyFn) => (
150
<div style={{
151
display: 'grid',
152
gap: '20px',
153
padding: '20px',
154
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))'
155
}}>
156
{storyFn()}
157
</div>
158
);
159
```
160
161
**Context Decorators:**
162
163
```javascript
164
// Router decorator for components needing routing context
165
import { BrowserRouter } from 'react-router-dom';
166
167
const RouterDecorator = (storyFn) => (
168
<BrowserRouter>
169
{storyFn()}
170
</BrowserRouter>
171
);
172
173
// Redux store decorator
174
import { Provider } from 'react-redux';
175
import store from '../src/store';
176
177
const ReduxDecorator = (storyFn) => (
178
<Provider store={store}>
179
{storyFn()}
180
</Provider>
181
);
182
```
183
184
**Information Decorators:**
185
186
```javascript
187
// Story info decorator showing component details
188
const InfoDecorator = (storyFn, context) => (
189
<div>
190
<div style={{
191
padding: '10px',
192
backgroundColor: '#f0f0f0',
193
marginBottom: '20px'
194
}}>
195
<strong>Component:</strong> {context.kind} <br/>
196
<strong>Story:</strong> {context.story}
197
</div>
198
{storyFn()}
199
</div>
200
);
201
```
202
203
## Types
204
205
```javascript { .api }
206
interface StoryDecorator {
207
/**
208
* Decorator function that wraps story components
209
* @param story - Function that returns the story component
210
* @param context - Story context information
211
* @returns JSX element wrapping the story
212
*/
213
(story: Function, context: StoryContext): Object;
214
}
215
216
interface StoryContext {
217
/** The story collection name */
218
kind: string;
219
/** The individual story name */
220
story: string;
221
}
222
```