useEventListener
Attach event listeners to any target - window, document, or an element - with automatic cleanup on teardown.
The target may be a reactive getter so the listener re-binds as the target changes. SSR-safe.
Window target
Target window with a getter () => window so it stays SSR-safe - the target is only read in the browser. The listener is removed automatically when the component unmounts.
Last key: (press any key)
<script lang="ts">
import { useEventListener } from 'sv5ui';
let keyPressed = $state('');
// Use a getter (() => window) so it stays SSR-safe -
// the target is only read in the browser, inside an effect.
useEventListener(() => window, 'keydown', (e) => {
keyPressed = e.key;
});
</script>
<p>Last key: <strong>{keyPressed || '(press any key)'}</strong></p>Reactive element target
Pass a getter () => el when the element is bound with bind:this. The hook re-attaches whenever the getter returns a new element.
<script lang="ts">
import { useEventListener } from 'sv5ui';
let el = $state<HTMLDivElement>();
let hovered = $state(false);
useEventListener(() => el, 'pointerenter', () => (hovered = true));
useEventListener(() => el, 'pointerleave', () => (hovered = false));
</script>
<div bind:this={el} class="rounded border p-4">
{hovered ? 'Hovering!' : 'Hover over me'}
</div>Multiple event types
Pass an array of event names to attach the same handler to all of them in one call.
<script lang="ts">
import { useEventListener } from 'sv5ui';
let active = $state(false);
let el = $state<HTMLButtonElement>();
// Listen to multiple events in one call
useEventListener(() => el, ['pointerenter', 'focus'], () => (active = true));
useEventListener(() => el, ['pointerleave', 'blur'], () => (active = false));
</script>
<button bind:this={el} class="rounded border px-3 py-1.5">
{active ? 'Active' : 'Hover or focus me'}
</button>Listener options
The fourth argument is passed directly to addEventListener. Use passive: true for scroll/touch handlers, once: true to fire once, or capture: true for capture phase.
See code - no visible output for this snippet.
<script lang="ts">
import { useEventListener } from 'sv5ui';
let clicks = $state(0);
// { once: true } - fires once then removes itself
useEventListener(() => window, 'click', () => clicks++, { once: false });
// { passive: true } - never calls preventDefault
useEventListener(() => document, 'scroll', () => console.log('scrolled'), { passive: true });
</script>Parameters
| Parameter | Type | Default |
|---|---|---|
target | Window | Document | HTMLElement | EventTarget | (() => …) | null | - |
type | string | string[] | - |
handler | (event) => void | - |
options | boolean | AddEventListenerOptions | undefined |