Actions
- Actions are element-level lifecycle functions that allow you to add custom functionality to DOM elements
- They’re called when an element is
- mounted (added to the DOM)
- Updated
- Unmounted (removed from the DOM)
- Often used for
- 3rd party library integrations
- Managing custom behaviors like tooltips or lazy loading
- adding event listeners or modifying DOM elements
// App.svelte
<script>
import Canvas from './Canvas.svelte';
import {trapFocus} from './actions.svelte.js'
...
</script>
<div class="menu" use:trapFocus>
//actions.svelte.js
export function trapFocus(node) {
...
$effect(() => {
focusable()[0]?.focus();
node.addEventListener('keydown', handleKeydown);
return () => {
node.removeEventListener('keydown', handleKeydown);
previous?.focus();
}
});
}
- when
<div class='menu'>
node is mounted to the DOM, an action function is called and in the action we have an effect. We add these in the effect:node.addEventListener
: when event is mountednode.removeEventListener
: when event is unmounted- event can be unmounted when element (e.g.,
<div class="menu">
) is no longer rendered due to a state change or conditional logic
- event can be unmounted when element (e.g.,
Adding parameters
<script>
import tippy from 'tippy.js';
let content = $state('Hello!');
function tooltip(node, fn) {
$effect(() => {
const tooltip = tippy(node, fn());
return tooltip.destroy;
});
}
</script>
<input bind:value={content} />
<button use:tooltip={() => ({ content })}>
Hover me
</button>
- we want to add a tooltip to the
<button>
using theTippy.js
library. The action already hasuse:tooltip
, but the action also needs to accept a function that returns some options to pass to Tippy