or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

animation.mdconfiguration.mdevents.mdindex.md

events.mddocs/

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

```