--- title: "JSX Event Handling" description: "How event binding works in @ecopages/jsx." group: JSX order: 4 --- # 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. ```tsx ``` ## Event Travel Still Matters The browser event model still applies: - `event.target` is where the event started - `event.currentTarget` is 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:*`. For example, `on:focus`, `on:blur`, `on:scroll`, `on:load`, and `on:dragstart` attach on the element even though you authored `on:*`, not `on-native:*`. ```tsx
``` ## 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](/docs/decorators/on-event) when you want class-level event subscription on a `RadiantElement` or `RadiantController`.