0
# Actions and Event Tracking
1
2
Action tracking system for logging and monitoring component interactions and events. Actions provide automatic event capture and manual action creation with configurable options for debugging and testing component behavior.
3
4
## Capabilities
5
6
### Single Action Creation
7
8
Creates a single action handler for tracking specific events.
9
10
```typescript { .api }
11
/**
12
* Create a single action handler for event tracking
13
* @param name - The display name for the action in the Actions panel
14
* @param options - Optional configuration for action behavior
15
* @returns Function that logs events when called
16
*/
17
function action(name: string, options?: ActionOptions): HandlerFunction;
18
19
type HandlerFunction = (...args: any[]) => void;
20
21
interface ActionOptions extends Partial<TelejsonOptions> {
22
/** Maximum depth for object serialization (default: 3) */
23
depth?: number;
24
/** Clear actions when story changes (default: true) */
25
clearOnStoryChange?: boolean;
26
/** Maximum number of actions to display (default: 5) */
27
limit?: number;
28
/** Mark as implicit action (for automatic detection) */
29
implicit?: boolean;
30
/** Custom identifier for the action */
31
id?: string;
32
// Additional serialization options inherited from TelejsonOptions
33
}
34
```
35
36
**Usage Example:**
37
38
```typescript
39
import { action } from "storybook/actions";
40
41
export const ButtonWithAction: Story = {
42
render: (args) => (
43
<button onClick={action("clicked")} {...args}>
44
Click me
45
</button>
46
),
47
args: {
48
children: "Button",
49
},
50
};
51
52
// With options
53
export const ButtonWithDetailedAction: Story = {
54
render: (args) => (
55
<button
56
onClick={action("button-clicked", {
57
depth: 5,
58
limit: 10
59
})}
60
{...args}
61
>
62
Click me
63
</button>
64
),
65
};
66
```
67
68
### Multiple Actions Creation
69
70
Creates multiple action handlers at once using various patterns.
71
72
```typescript { .api }
73
/**
74
* Create multiple action handlers from a list of names
75
* @param handlers - Array of action names
76
* @returns Object mapping each name to its action handler
77
*/
78
function actions<T extends string>(...handlers: T[]): ActionsMap<T>;
79
80
/**
81
* Create multiple action handlers from a name-to-display mapping
82
* @param handlerMap - Object mapping handler names to display names
83
* @param options - Optional configuration applied to all actions
84
* @returns Object mapping each handler name to its action function
85
*/
86
function actions<T extends string>(
87
handlerMap: Record<T, string>,
88
options?: ActionOptions
89
): ActionsMap<T>;
90
91
type ActionsMap<T extends string> = Record<T, HandlerFunction>;
92
```
93
94
**Usage Examples:**
95
96
```typescript
97
import { actions } from "storybook/actions";
98
99
// Create actions from names
100
const eventHandlers = actions("onClick", "onHover", "onFocus");
101
102
export const InteractiveComponent: Story = {
103
render: (args) => (
104
<div
105
onClick={eventHandlers.onClick}
106
onMouseEnter={eventHandlers.onHover}
107
onFocus={eventHandlers.onFocus}
108
{...args}
109
>
110
Interactive element
111
</div>
112
),
113
};
114
115
// Create actions with custom display names
116
const customActions = actions(
117
{
118
handleSubmit: "Form submitted",
119
handleCancel: "Form cancelled",
120
handleReset: "Form reset",
121
},
122
{ depth: 4 }
123
);
124
125
export const FormComponent: Story = {
126
render: (args) => (
127
<form>
128
<button type="submit" onClick={customActions.handleSubmit}>
129
Submit
130
</button>
131
<button type="button" onClick={customActions.handleCancel}>
132
Cancel
133
</button>
134
<button type="reset" onClick={customActions.handleReset}>
135
Reset
136
</button>
137
</form>
138
),
139
};
140
```
141
142
### Legacy Decorator (Deprecated)
143
144
The `withActions` decorator is deprecated in Storybook v10+ but still available for backward compatibility.
145
146
```typescript { .api }
147
/**
148
* Legacy decorator for automatic action detection
149
* @deprecated Use action() function directly instead
150
*/
151
const withActions: DecoratorFunction;
152
```
153
154
## Action Configuration
155
156
### Global Action Parameters
157
158
Configure actions behavior at the story or project level using parameters.
159
160
```typescript { .api }
161
interface ActionParameters {
162
/** Automatically create actions for props matching this regex */
163
argTypesRegex?: string;
164
/** Disable actions entirely */
165
disable?: boolean;
166
/** Array of specific prop names to create actions for */
167
handles?: string[];
168
}
169
```
170
171
**Usage Example:**
172
173
```typescript
174
// In .storybook/preview.js or story parameters
175
export const parameters = {
176
actions: {
177
argTypesRegex: "^on[A-Z].*" // Automatically create actions for props starting with "on"
178
}
179
};
180
181
// Or per story
182
export const MyStory: Story = {
183
parameters: {
184
actions: {
185
handles: ["onClick", "onSubmit", "onCancel"]
186
}
187
}
188
};
189
```
190
191
## Events and Constants
192
193
```typescript { .api }
194
/** Action addon identifier */
195
const ADDON_ID = "storybook/actions";
196
197
/** Parameter key for action configuration */
198
const PARAM_KEY = "actions";
199
200
/** Event emitted when an action occurs */
201
const EVENT_ID = "storybook/action";
202
203
/** Event emitted to clear all actions */
204
const CLEAR_ID = "storybook/clear-actions";
205
```
206
207
## Action Display Types
208
209
```typescript { .api }
210
interface ActionDisplay {
211
/** Unique identifier for the action event */
212
id: string;
213
/** Number of times this action has been triggered */
214
count: number;
215
/** Action data including name and arguments */
216
data: {
217
name: string;
218
args: any[];
219
};
220
/** Configuration options used for this action */
221
options: ActionOptions;
222
}
223
```
224
225
## Advanced Usage Patterns
226
227
### Custom Action Serialization
228
229
```typescript
230
import { action } from "storybook/actions";
231
232
// Custom serialization for complex objects
233
const handleComplexEvent = action("complex-event", {
234
depth: 10, // Deep serialization
235
limit: 20 // More history
236
});
237
238
export const ComplexComponent: Story = {
239
render: () => (
240
<ComplexForm
241
onSubmit={(formData) => {
242
handleComplexEvent({
243
timestamp: Date.now(),
244
formData,
245
validationErrors: formData.errors
246
});
247
}}
248
/>
249
),
250
};
251
```
252
253
### Conditional Actions
254
255
```typescript
256
import { action } from "storybook/actions";
257
258
const conditionalAction = (condition: boolean) =>
259
condition ? action("conditional-action") : () => {};
260
261
export const ConditionalStory: Story = {
262
render: (args) => (
263
<button onClick={conditionalAction(args.enableLogging)}>
264
Click me
265
</button>
266
),
267
args: {
268
enableLogging: true,
269
},
270
argTypes: {
271
enableLogging: { control: "boolean" },
272
},
273
};
274
```
275
276
### Integration with Component Props
277
278
```typescript
279
import { actions } from "storybook/actions";
280
281
interface ButtonProps {
282
onClick?: () => void;
283
onDoubleClick?: () => void;
284
onMouseEnter?: () => void;
285
}
286
287
const eventHandlers = actions("onClick", "onDoubleClick", "onMouseEnter");
288
289
export const FullyTrackedButton: Story<ButtonProps> = {
290
render: (args) => <Button {...args} {...eventHandlers} />,
291
args: {
292
children: "Tracked Button",
293
},
294
};
295
```