0
# Event Handling
1
2
Comprehensive callback system for responding to state changes and user interactions throughout the collapsible component lifecycle.
3
4
## Capabilities
5
6
### Trigger Click Handling
7
8
Custom control over trigger click behavior and state management.
9
10
```typescript { .api }
11
/**
12
* Custom handler for trigger click events
13
* When provided, overrides default open/close behavior
14
* Receives accordionPosition if specified
15
* @param accordionPosition - The accordionPosition prop value if provided
16
*/
17
handleTriggerClick?: (accordionPosition?: string | number) => void;
18
```
19
20
**Usage Examples:**
21
22
```jsx
23
// Basic controlled usage
24
const [isOpen, setIsOpen] = useState(false);
25
26
<Collapsible
27
trigger="Custom click handler"
28
open={isOpen}
29
handleTriggerClick={() => {
30
console.log('Trigger clicked!');
31
setIsOpen(!isOpen);
32
}}
33
>
34
<p>Controlled content</p>
35
</Collapsible>
36
37
// Accordion pattern with position tracking
38
const [openSections, setOpenSections] = useState(new Set());
39
40
const handleAccordionClick = (position) => {
41
const newOpenSections = new Set(openSections);
42
if (newOpenSections.has(position)) {
43
newOpenSections.delete(position);
44
} else {
45
newOpenSections.add(position);
46
}
47
setOpenSections(newOpenSections);
48
};
49
50
{items.map((item, index) => (
51
<Collapsible
52
key={item.id}
53
trigger={item.title}
54
open={openSections.has(index)}
55
accordionPosition={index}
56
handleTriggerClick={handleAccordionClick}
57
>
58
<div>{item.content}</div>
59
</Collapsible>
60
))}
61
```
62
63
### Animation Lifecycle Events
64
65
Events that fire at different stages of the opening and closing animations.
66
67
```typescript { .api }
68
/**
69
* Called when the opening animation begins
70
* Fires immediately when user clicks to open or open prop becomes true
71
*/
72
onOpening?: () => void;
73
74
/**
75
* Called when the opening animation completes
76
* Fires after the component is fully expanded and animation finished
77
*/
78
onOpen?: () => void;
79
80
/**
81
* Called when the closing animation begins
82
* Fires immediately when user clicks to close or open prop becomes false
83
*/
84
onClosing?: () => void;
85
86
/**
87
* Called when the closing animation completes
88
* Fires after the component is fully collapsed and animation finished
89
*/
90
onClose?: () => void;
91
```
92
93
**Animation Timeline:**
94
95
1. User clicks trigger or `open` prop changes
96
2. `onOpening` or `onClosing` fires immediately
97
3. CSS animation runs (duration: `transitionTime` or `transitionCloseTime`)
98
4. `onOpen` or `onClose` fires when animation completes
99
100
**Usage Examples:**
101
102
```jsx
103
// Track animation state
104
const [animationState, setAnimationState] = useState('closed');
105
106
<Collapsible
107
trigger="Animation tracking"
108
onOpening={() => {
109
console.log('Starting to open...');
110
setAnimationState('opening');
111
}}
112
onOpen={() => {
113
console.log('Fully opened!');
114
setAnimationState('open');
115
}}
116
onClosing={() => {
117
console.log('Starting to close...');
118
setAnimationState('closing');
119
}}
120
onClose={() => {
121
console.log('Fully closed!');
122
setAnimationState('closed');
123
}}
124
>
125
<div>Animation state: {animationState}</div>
126
</Collapsible>
127
128
// Analytics tracking
129
<Collapsible
130
trigger="Tracked content"
131
onOpen={() => {
132
analytics.track('collapsible_opened', {
133
section: 'faq-section-1'
134
});
135
}}
136
onClose={() => {
137
analytics.track('collapsible_closed', {
138
section: 'faq-section-1'
139
});
140
}}
141
>
142
<p>Content with analytics tracking</p>
143
</Collapsible>
144
```
145
146
### Trigger-Specific Events
147
148
Events that fire specifically in response to user clicking the trigger element.
149
150
```typescript { .api }
151
/**
152
* Called when user clicks trigger to open the collapsible
153
* Only fires for actual user clicks, not programmatic state changes
154
*/
155
onTriggerOpening?: () => void;
156
157
/**
158
* Called when user clicks trigger to close the collapsible
159
* Only fires for actual user clicks, not programmatic state changes
160
*/
161
onTriggerClosing?: () => void;
162
```
163
164
**Difference from Animation Events:**
165
166
- **Animation events** (`onOpening`, `onClosing`) fire for both user clicks AND programmatic `open` prop changes
167
- **Trigger events** (`onTriggerOpening`, `onTriggerClosing`) fire ONLY when user actually clicks the trigger
168
169
**Usage Examples:**
170
171
```jsx
172
// Distinguish between user actions and programmatic changes
173
const [userInteractions, setUserInteractions] = useState(0);
174
175
<Collapsible
176
trigger="User interaction tracking"
177
onOpening={() => console.log('Opening (any cause)')}
178
onTriggerOpening={() => {
179
console.log('User clicked to open');
180
setUserInteractions(prev => prev + 1);
181
}}
182
onClosing={() => console.log('Closing (any cause)')}
183
onTriggerClosing={() => {
184
console.log('User clicked to close');
185
setUserInteractions(prev => prev + 1);
186
}}
187
>
188
<p>User interactions: {userInteractions}</p>
189
</Collapsible>
190
191
// Auto-close with user action detection
192
const [autoCloseTimer, setAutoCloseTimer] = useState(null);
193
194
<Collapsible
195
trigger="Auto-closing content"
196
onTriggerOpening={() => {
197
// Clear any existing auto-close timer when user opens
198
if (autoCloseTimer) {
199
clearTimeout(autoCloseTimer);
200
setAutoCloseTimer(null);
201
}
202
}}
203
onOpen={() => {
204
// Set auto-close timer after opening completes
205
const timer = setTimeout(() => {
206
// Programmatically close (won't trigger onTriggerClosing)
207
setIsOpen(false);
208
}, 5000);
209
setAutoCloseTimer(timer);
210
}}
211
>
212
<p>This will auto-close in 5 seconds unless you interact with it</p>
213
</Collapsible>
214
```
215
216
## Event Combinations and Patterns
217
218
### Complete Event Flow Example
219
220
```jsx
221
const EventLogger = () => {
222
const [logs, setLogs] = useState([]);
223
const [isOpen, setIsOpen] = useState(false);
224
225
const addLog = (message) => {
226
setLogs(prev => [...prev, `${new Date().toLocaleTimeString()}: ${message}`]);
227
};
228
229
return (
230
<div>
231
<Collapsible
232
trigger="Complete event logging"
233
open={isOpen}
234
handleTriggerClick={() => {
235
addLog('handleTriggerClick called');
236
setIsOpen(!isOpen);
237
}}
238
onTriggerOpening={() => addLog('onTriggerOpening: User clicked to open')}
239
onOpening={() => addLog('onOpening: Opening animation started')}
240
onOpen={() => addLog('onOpen: Opening animation completed')}
241
onTriggerClosing={() => addLog('onTriggerClosing: User clicked to close')}
242
onClosing={() => addLog('onClosing: Closing animation started')}
243
onClose={() => addLog('onClose: Closing animation completed')}
244
transitionTime={1000} // Longer animation to see the sequence
245
>
246
<div>
247
<h4>Event Log:</h4>
248
<ul>
249
{logs.map((log, index) => (
250
<li key={index}>{log}</li>
251
))}
252
</ul>
253
</div>
254
</Collapsible>
255
256
<button onClick={() => setIsOpen(!isOpen)}>
257
Programmatic Toggle (won't trigger onTrigger* events)
258
</button>
259
</div>
260
);
261
};
262
```
263
264
### Accordion with Event Coordination
265
266
```jsx
267
const AccordionWithEvents = () => {
268
const [openItems, setOpenItems] = useState(new Set());
269
const [lastAction, setLastAction] = useState('');
270
271
const handleItemClick = (position) => {
272
const newOpenItems = new Set(openItems);
273
const wasOpen = newOpenItems.has(position);
274
275
if (wasOpen) {
276
newOpenItems.delete(position);
277
setLastAction(`Closed item ${position}`);
278
} else {
279
newOpenItems.add(position);
280
setLastAction(`Opened item ${position}`);
281
}
282
283
setOpenItems(newOpenItems);
284
};
285
286
const items = [
287
{ title: 'Section 1', content: 'Content for section 1' },
288
{ title: 'Section 2', content: 'Content for section 2' },
289
{ title: 'Section 3', content: 'Content for section 3' }
290
];
291
292
return (
293
<div>
294
<p>Last action: {lastAction}</p>
295
{items.map((item, index) => (
296
<Collapsible
297
key={index}
298
trigger={item.title}
299
open={openItems.has(index)}
300
accordionPosition={index}
301
handleTriggerClick={handleItemClick}
302
onOpen={() => console.log(`Section ${index} finished opening`)}
303
onClose={() => console.log(`Section ${index} finished closing`)}
304
>
305
<div>{item.content}</div>
306
</Collapsible>
307
))}
308
</div>
309
);
310
};
311
```