0
# Addons
1
2
Extensible plugin system for adding custom functionality to the Storybook interface and development workflow. Addons provide additional methods to the Story API and can integrate with the Storybook UI.
3
4
## Capabilities
5
6
### Set Addon
7
8
Registers addon methods to the Story API, making them available as chainable methods on story collections.
9
10
```javascript { .api }
11
/**
12
* Registers addon methods to the Story API
13
* @param addon - Object containing methods to add to Story instances
14
*/
15
function setAddon(addon: Object): void;
16
```
17
18
**Usage Examples:**
19
20
```javascript
21
import { setAddon, storiesOf } from '@kadira/storybook';
22
23
// Simple addon that adds a method to stories
24
setAddon({
25
addWithInfo(storyName, info, storyFn) {
26
return this.add(storyName, () => (
27
<div>
28
<div style={{ padding: '10px', backgroundColor: '#f0f0f0' }}>
29
<strong>Info:</strong> {info}
30
</div>
31
{storyFn()}
32
</div>
33
));
34
}
35
});
36
37
// Now use the addon method on any story collection
38
storiesOf('Button', module)
39
.addWithInfo('default', 'A basic button component', () =>
40
<Button>Click me</Button>
41
)
42
.addWithInfo('primary', 'Primary variant of the button', () =>
43
<Button primary>Primary</Button>
44
);
45
46
// Multiple addon methods
47
setAddon({
48
addWithProps(name, props, component) {
49
return this.add(name, () => React.createElement(component, props));
50
},
51
52
addVariants(baseName, variants, component) {
53
variants.forEach(variant => {
54
this.add(`${baseName} - ${variant.name}`, () =>
55
React.createElement(component, variant.props)
56
);
57
});
58
return this;
59
}
60
});
61
62
// Usage of multiple addon methods
63
storiesOf('Input', module)
64
.addWithProps('disabled', { disabled: true, value: 'Disabled' }, Input)
65
.addVariants('sizes', [
66
{ name: 'small', props: { size: 'small' } },
67
{ name: 'large', props: { size: 'large' } }
68
], Input);
69
```
70
71
### Built-in Addons
72
73
Storybook comes with several built-in addons that provide common functionality.
74
75
#### Storybook Addons Core
76
77
The core addon system that manages addon registration and communication.
78
79
```javascript
80
import addons from '@kadira/storybook-addons';
81
82
// Access the addon channel for custom communication
83
const channel = addons.getChannel();
84
channel.emit('my-event', { data: 'example' });
85
```
86
87
#### Actions Addon
88
89
Built-in addon for logging component interactions and events.
90
91
```javascript
92
import { action } from '@kadira/storybook-addon-actions';
93
94
// Available as re-export from main package
95
import { action } from '@kadira/storybook';
96
97
storiesOf('Interactive Button', module)
98
.add('with click handler', () => (
99
<Button onClick={action('button-clicked')}>
100
Click me to see action log
101
</Button>
102
))
103
.add('with multiple events', () => (
104
<Input
105
onChange={action('input-changed')}
106
onFocus={action('input-focused')}
107
onBlur={action('input-blurred')}
108
/>
109
));
110
```
111
112
#### Links Addon
113
114
Built-in addon for creating navigation links between stories.
115
116
```javascript
117
import { linkTo } from '@kadira/storybook-addon-links';
118
119
// Available as re-export from main package
120
import { linkTo } from '@kadira/storybook';
121
122
storiesOf('Navigation', module)
123
.add('go to button', () => (
124
<div>
125
<p>Click below to navigate to Button stories</p>
126
<button onClick={linkTo('Button', 'default')}>
127
Go to Button Default
128
</button>
129
</div>
130
))
131
.add('conditional navigation', () => (
132
<Button onClick={linkTo('Form', 'input')}>
133
Go to Form Input Story
134
</Button>
135
));
136
```
137
138
### Custom Addon Development
139
140
Creating custom addons for specific project needs.
141
142
**Basic Custom Addon:**
143
144
```javascript
145
// Define the addon object
146
const myCustomAddon = {
147
addWithWrapper(storyName, wrapperStyle, storyFn) {
148
return this.add(storyName, () => (
149
<div style={wrapperStyle}>
150
{storyFn()}
151
</div>
152
));
153
},
154
155
addWithBackground(storyName, backgroundColor, storyFn) {
156
return this.addWithWrapper(storyName, { backgroundColor }, storyFn);
157
}
158
};
159
160
// Register the addon
161
setAddon(myCustomAddon);
162
163
// Use the addon methods
164
storiesOf('Styled Components', module)
165
.addWithBackground('on blue', '#e3f2fd', () => <Card />)
166
.addWithBackground('on green', '#e8f5e8', () => <Card />);
167
```
168
169
**Advanced Custom Addon with State:**
170
171
```javascript
172
const stateAddon = {
173
addWithState(storyName, initialState, storyFn) {
174
return this.add(storyName, () => {
175
const [state, setState] = React.useState(initialState);
176
return storyFn(state, setState);
177
});
178
}
179
};
180
181
setAddon(stateAddon);
182
183
storiesOf('Stateful Components', module)
184
.addWithState('counter', { count: 0 }, (state, setState) => (
185
<div>
186
<p>Count: {state.count}</p>
187
<button onClick={() => setState({ count: state.count + 1 })}>
188
Increment
189
</button>
190
</div>
191
));
192
```
193
194
### Addon File Structure
195
196
Standard addon development typically follows this structure:
197
198
```
199
my-custom-addon/
200
├── package.json
201
├── src/
202
│ ├── index.js # Main addon logic
203
│ ├── register.js # UI panel registration
204
│ └── components/ # Addon UI components
205
└── README.md
206
```
207
208
**Example Addon Entry Point:**
209
210
```javascript
211
// src/index.js
212
export const myAddon = {
213
addWithCustomLayout(storyName, layoutProps, storyFn) {
214
return this.add(storyName, () => (
215
<CustomLayout {...layoutProps}>
216
{storyFn()}
217
</CustomLayout>
218
));
219
}
220
};
221
222
// Auto-register if imported
223
import { setAddon } from '@kadira/storybook';
224
setAddon(myAddon);
225
```
226
227
## Types
228
229
```javascript { .api }
230
interface AddonObject {
231
/** Custom methods to add to Story API */
232
[methodName: string]: Function;
233
}
234
235
interface StoryAPI {
236
/** Add a story to this collection */
237
add(storyName: string, storyFunction: Function): StoryAPI;
238
/** Add a decorator to this collection */
239
addDecorator(decorator: Function): StoryAPI;
240
/** The story collection name */
241
kind: string;
242
/** Any addon methods registered via setAddon */
243
[addonMethod: string]: Function;
244
}
245
```