or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

css-styling.mdevent-handling.mdforms-inputs.mdhtml-elements.mdindex.mdsvg-support.md

event-handling.mddocs/

0

# Event Handling

1

2

Comprehensive event system with synthetic events that wrap native browser events while providing type safety and consistent APIs across different event types.

3

4

## Capabilities

5

6

### Event System Overview

7

8

All events in Compose Web are synthetic events that wrap native DOM events with additional type safety and consistent behavior.

9

10

```kotlin { .api }

11

/**

12

* Base synthetic event interface

13

* @param T Native event type

14

*/

15

interface SyntheticEvent<T : Event> {

16

val nativeEvent: T

17

val target: EventTarget?

18

val currentTarget: EventTarget?

19

fun preventDefault()

20

fun stopPropagation()

21

}

22

```

23

24

### Mouse Events

25

26

Mouse interaction events for clicks, movements, and button states.

27

28

```kotlin { .api }

29

/**

30

* Mouse event interface extending SyntheticEvent

31

*/

32

interface SyntheticMouseEvent : SyntheticEvent<MouseEvent> {

33

val clientX: Int

34

val clientY: Int

35

val button: Short

36

val buttons: Short

37

val altKey: Boolean

38

val ctrlKey: Boolean

39

val metaKey: Boolean

40

val shiftKey: Boolean

41

}

42

43

/**

44

* Mouse event listeners (available in EventsListenerScope)

45

*/

46

fun EventsListenerScope.onClick(listener: (SyntheticMouseEvent) -> Unit)

47

fun EventsListenerScope.onDoubleClick(listener: (SyntheticMouseEvent) -> Unit)

48

fun EventsListenerScope.onMouseDown(listener: (SyntheticMouseEvent) -> Unit)

49

fun EventsListenerScope.onMouseUp(listener: (SyntheticMouseEvent) -> Unit)

50

fun EventsListenerScope.onMouseEnter(listener: (SyntheticMouseEvent) -> Unit)

51

fun EventsListenerScope.onMouseLeave(listener: (SyntheticMouseEvent) -> Unit)

52

fun EventsListenerScope.onMouseMove(listener: (SyntheticMouseEvent) -> Unit)

53

fun EventsListenerScope.onMouseOut(listener: (SyntheticMouseEvent) -> Unit)

54

fun EventsListenerScope.onMouseOver(listener: (SyntheticMouseEvent) -> Unit)

55

fun EventsListenerScope.onWheel(listener: (SyntheticWheelEvent) -> Unit)

56

```

57

58

### Keyboard Events

59

60

Keyboard input events for key presses and releases.

61

62

```kotlin { .api }

63

/**

64

* Keyboard event interface

65

*/

66

interface SyntheticKeyboardEvent : SyntheticEvent<KeyboardEvent> {

67

val key: String

68

val code: String

69

val keyCode: Int

70

val altKey: Boolean

71

val ctrlKey: Boolean

72

val metaKey: Boolean

73

val shiftKey: Boolean

74

val repeat: Boolean

75

}

76

77

/**

78

* Keyboard event listeners

79

*/

80

fun EventsListenerScope.onKeyDown(listener: (SyntheticKeyboardEvent) -> Unit)

81

fun EventsListenerScope.onKeyUp(listener: (SyntheticKeyboardEvent) -> Unit)

82

```

83

84

### Focus Events

85

86

Focus and blur events for element focus state changes.

87

88

```kotlin { .api }

89

/**

90

* Focus event interface

91

*/

92

interface SyntheticFocusEvent : SyntheticEvent<FocusEvent> {

93

val relatedTarget: EventTarget?

94

}

95

96

/**

97

* Focus event listeners

98

*/

99

fun EventsListenerScope.onFocus(listener: (SyntheticFocusEvent) -> Unit)

100

fun EventsListenerScope.onBlur(listener: (SyntheticFocusEvent) -> Unit)

101

fun EventsListenerScope.onFocusIn(listener: (SyntheticFocusEvent) -> Unit)

102

fun EventsListenerScope.onFocusOut(listener: (SyntheticFocusEvent) -> Unit)

103

```

104

105

### Input Events

106

107

Input value change events for form elements.

108

109

```kotlin { .api }

110

/**

111

* Input event interface for value changes

112

*/

113

interface SyntheticInputEvent : SyntheticEvent<InputEvent> {

114

val data: String?

115

val inputType: String

116

}

117

118

/**

119

* Change event interface for form controls

120

*/

121

interface SyntheticChangeEvent : SyntheticEvent<Event> {

122

val target: EventTarget?

123

}

124

125

/**

126

* Text selection event interface

127

*/

128

interface SyntheticSelectEvent : SyntheticEvent<Event>

129

130

/**

131

* Input event listeners

132

*/

133

fun EventsListenerScope.onInput(listener: (SyntheticInputEvent) -> Unit)

134

fun EventsListenerScope.onChange(listener: (SyntheticChangeEvent) -> Unit)

135

fun EventsListenerScope.onSelect(listener: (SyntheticSelectEvent) -> Unit)

136

```

137

138

### Form Events

139

140

Form submission and reset events.

141

142

```kotlin { .api }

143

/**

144

* Form submission event interface

145

*/

146

interface SyntheticSubmitEvent : SyntheticEvent<SubmitEvent>

147

148

/**

149

* Form event listeners

150

*/

151

fun EventsListenerScope.onSubmit(listener: (SyntheticSubmitEvent) -> Unit)

152

fun EventsListenerScope.onReset(listener: (SyntheticEvent<Event>) -> Unit)

153

```

154

155

### Touch Events

156

157

Touch interaction events for mobile and touch-enabled devices.

158

159

```kotlin { .api }

160

/**

161

* Touch event interface

162

*/

163

interface SyntheticTouchEvent : SyntheticEvent<TouchEvent> {

164

val touches: TouchList

165

val targetTouches: TouchList

166

val changedTouches: TouchList

167

val altKey: Boolean

168

val ctrlKey: Boolean

169

val metaKey: Boolean

170

val shiftKey: Boolean

171

}

172

173

/**

174

* Touch event listeners

175

*/

176

fun EventsListenerScope.onTouchStart(listener: (SyntheticTouchEvent) -> Unit)

177

fun EventsListenerScope.onTouchEnd(listener: (SyntheticTouchEvent) -> Unit)

178

fun EventsListenerScope.onTouchMove(listener: (SyntheticTouchEvent) -> Unit)

179

fun EventsListenerScope.onTouchCancel(listener: (SyntheticTouchEvent) -> Unit)

180

```

181

182

### Animation Events

183

184

CSS animation lifecycle events.

185

186

```kotlin { .api }

187

/**

188

* Animation event interface for CSS animations

189

*/

190

interface SyntheticAnimationEvent : SyntheticEvent<AnimationEvent> {

191

val animationName: String

192

val elapsedTime: Double

193

val pseudoElement: String

194

}

195

196

/**

197

* Animation event listeners

198

*/

199

fun EventsListenerScope.onAnimationStart(listener: (SyntheticAnimationEvent) -> Unit)

200

fun EventsListenerScope.onAnimationEnd(listener: (SyntheticAnimationEvent) -> Unit)

201

fun EventsListenerScope.onAnimationIteration(listener: (SyntheticAnimationEvent) -> Unit)

202

```

203

204

### Clipboard Events

205

206

Clipboard operation events for copy, cut, and paste operations.

207

208

```kotlin { .api }

209

/**

210

* Clipboard event interface

211

*/

212

interface SyntheticClipboardEvent : SyntheticEvent<ClipboardEvent> {

213

val clipboardData: DataTransfer?

214

}

215

216

/**

217

* Clipboard event listeners

218

*/

219

fun EventsListenerScope.onCopy(listener: (SyntheticClipboardEvent) -> Unit)

220

fun EventsListenerScope.onCut(listener: (SyntheticClipboardEvent) -> Unit)

221

fun EventsListenerScope.onPaste(listener: (SyntheticClipboardEvent) -> Unit)

222

```

223

224

### Event Handler Context

225

226

Event listeners are used within the attrs builder context of HTML elements.

227

228

```kotlin { .api }

229

/**

230

* Event listener scope available within attrs builders

231

*/

232

interface EventsListenerScope

233

234

/**

235

* Attributes scope that includes event listener scope

236

*/

237

interface AttrsScope<out TElement : Element> : EventsListenerScope

238

```

239

240

**Usage Examples:**

241

242

```kotlin

243

import org.jetbrains.compose.web.dom.*

244

import org.jetbrains.compose.web.events.*

245

246

// Mouse events

247

Button({

248

onClick { event ->

249

console.log("Button clicked at (${event.clientX}, ${event.clientY})")

250

if (event.ctrlKey) {

251

console.log("Ctrl key was held")

252

}

253

}

254

255

onDoubleClick { event ->

256

console.log("Button double-clicked")

257

event.preventDefault()

258

}

259

}) {

260

Text("Click Me")

261

}

262

263

// Keyboard events

264

TextInput(value = "", {

265

onKeyDown { event ->

266

when (event.key) {

267

"Enter" -> {

268

console.log("Enter key pressed")

269

// Handle form submission

270

}

271

"Escape" -> {

272

console.log("Escape key pressed")

273

// Clear input or close dialog

274

}

275

else -> {

276

console.log("Key pressed: ${event.key}")

277

}

278

}

279

}

280

281

onKeyUp { event ->

282

if (event.ctrlKey && event.key == "z") {

283

console.log("Undo shortcut detected")

284

}

285

}

286

})

287

288

// Focus events

289

TextInput(value = "", {

290

onFocus { event ->

291

console.log("Input focused")

292

// Show help text or highlight field

293

}

294

295

onBlur { event ->

296

console.log("Input lost focus")

297

// Validate input or hide help text

298

}

299

})

300

301

// Input events for reactive updates

302

var inputValue by remember { mutableStateOf("") }

303

304

TextInput(value = inputValue, {

305

onInput { event ->

306

// Update state on every character typed

307

inputValue = (event.target as HTMLInputElement).value

308

console.log("Input value: $inputValue")

309

}

310

311

onChange { event ->

312

// Fires on blur, useful for validation

313

val value = (event.target as HTMLInputElement).value

314

console.log("Final value: $value")

315

}

316

})

317

318

// Form events

319

Form({

320

onSubmit { event ->

321

event.preventDefault() // Prevent default form submission

322

console.log("Form submitted")

323

324

// Handle form data

325

val formData = FormData(event.target as HTMLFormElement)

326

// Process form data...

327

}

328

329

onReset { event ->

330

console.log("Form reset")

331

// Clear custom state if needed

332

}

333

}) {

334

TextInput(name = "username")

335

PasswordInput(name = "password")

336

SubmitInput()

337

}

338

339

// Touch events for mobile

340

Div({

341

onTouchStart { event ->

342

console.log("Touch started with ${event.touches.length} fingers")

343

}

344

345

onTouchMove { event ->

346

event.preventDefault() // Prevent scrolling

347

val touch = event.touches[0]

348

console.log("Touch moved to (${touch.clientX}, ${touch.clientY})")

349

}

350

351

onTouchEnd { event ->

352

console.log("Touch ended")

353

}

354

}) {

355

Text("Touch-enabled area")

356

}

357

358

// Animation events

359

Div({

360

classes("animated-element")

361

362

onAnimationStart { event ->

363

console.log("Animation '${event.animationName}' started")

364

}

365

366

onAnimationEnd { event ->

367

console.log("Animation '${event.animationName}' completed after ${event.elapsedTime}s")

368

}

369

370

onAnimationIteration { event ->

371

console.log("Animation '${event.animationName}' iteration completed")

372

}

373

}) {

374

Text("Animated content")

375

}

376

377

// Clipboard events

378

TextArea({

379

onCopy { event ->

380

console.log("Text copied to clipboard")

381

val selectedText = window.getSelection()?.toString()

382

console.log("Copied text: $selectedText")

383

}

384

385

onPaste { event ->

386

val pastedData = event.clipboardData?.getData("text/plain")

387

console.log("Pasted text: $pastedData")

388

389

// Optionally prevent default and handle custom paste logic

390

// event.preventDefault()

391

}

392

})

393

394

// Event delegation example

395

Div({

396

onClick { event ->

397

// This will catch clicks from child elements due to event bubbling

398

val clickedElement = event.target as? Element

399

console.log("Clicked element: ${clickedElement?.tagName}")

400

401

// Stop propagation if needed

402

if (clickedElement?.classList?.contains("no-bubble") == true) {

403

event.stopPropagation()

404

}

405

}

406

}) {

407

Button { Text("Child Button 1") }

408

Button({ classes("no-bubble") }) { Text("Child Button 2 (no bubble)") }

409

P { Text("Clickable paragraph") }

410

}

411

```