JSX Event Handling
Radiant JSX does not invent a synthetic event system. Handlers receive the native browser Event object.
Two Binding Modes
| Use this | When you want | Runtime behavior |
|---|---|---|
on:* | The normal event API | Delegates a fixed allowlist of bubbling events and falls back to direct listeners otherwise |
on-native:* | Exact element-level browser semantics | Always calls addEventListener(...) on that element |
on:* is the default.
<button on:click={handleClick}>Save</button>
<button on-native:click={handleNativeClick}>Save with native attachment</button>Event Travel Still Matters
The browser event model still applies:
event.targetis where the event startedevent.currentTargetis the element whose listener is currently running- delegation only works for events that bubble
That is why delegated event support is limited to a documented allowlist of bubbling events.
Delegated Allowlist
on:* delegates these bubbling events:
beforeinput, click, contextmenu, dblclick, focusin, focusout, input, keydown, keyup, mousedown, mouseout, mouseover, mouseup, pointerdown, pointerout, pointerover, pointerup, touchend, touchmove, and touchstart.
Events outside that allowlist already attach directly when authored with on:*.
When To Use on-native:*
Use on-native:* when exact attachment semantics matter, for example:
- an ancestor may stop propagation before the delegated root listener runs
- you want to opt out of delegation for a supported bubbling event
- you are debugging exact listener placement
Relationship To @onEvent(...)
on:* and on-native:* are JSX-level event bindings.
Use @onEvent when you want class-level event subscription on a RadiantElement or RadiantController.