docs: copy Svelte 5 docs from omnisite ()

pull/12385/head
Ben McCann 9 months ago committed by GitHub
parent bdc45fdf7f
commit 145d67a489
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,3 +0,0 @@
{
"title": "Getting Started"
}

@ -0,0 +1,30 @@
---
title: Overview
---
- Short intro to what Svelte is and why it's the best ever
- A few code examples to have a very rough understanding of how Svelte code looks like
- Jump off points to tutorial, SvelteKit etc
Svelte is a web UI framework that uses a compiler to turn declarative component code like this...
```svelte
<!--- file: App.svelte --->
<script lang="ts">
let count = $state(0);
function increment() {
count += 1;
}
</script>
<button onclick={increment}>
clicks: {count}
</button>
```
...into tightly optimized JavaScript that updates the document when state like count changes. Because the compiler can 'see' where count is referenced, the generated code is highly efficient, and because we're hijacking syntax like `$state(...)` and `=` instead of using cumbersome APIs, you can write less code.
Besides being fun to work with, Svelte offers a lot of features built-in, such as animations and transitions. Once you've written your first components you can reach for our batteries included metaframework [SvelteKit](/docs/kit) which provides you with an opinionated router, data loading and more.
If you're new to Svelte, visit the [interactive tutorial](/tutorial) before consulting this documentation. You can try Svelte online using the [REPL](/repl). Alternatively, if you'd like a more fully-featured environment, you can try Svelte on [StackBlitz](https://sveltekit.new).

@ -1,10 +1,11 @@
---
title: Introduction
title: Getting started
---
Welcome to the Svelte reference documentation! This is intended as a resource for people who already have some familiarity with Svelte and want to learn more about using it.
If that's not you (yet), you may prefer to visit the [interactive tutorial](https://learn.svelte.dev) or the [examples](/examples) before consulting this reference. You can try Svelte online using the [REPL](/repl). Alternatively, if you'd like a more fully-featured environment, you can try Svelte on [StackBlitz](https://sveltekit.new).
- `npm create svelte@latest`, describe that it scaffolds SvelteKit project
- `npm create vite@latest`, describe that it scaffolds Svelte SPA powered by Vite
- mention `svelte-add`
- Jump off points to tutorial, SvelteKit etc
## Start a new project
@ -19,15 +20,19 @@ npm run dev
SvelteKit will handle calling [the Svelte compiler](https://www.npmjs.com/package/svelte) to convert your `.svelte` files into `.js` files that create the DOM and `.css` files that style it. It also provides all the other pieces you need to build a web application such as a development server, routing, deployment, and SSR support. [SvelteKit](https://kit.svelte.dev/) uses [Vite](https://vitejs.dev/) to build your code.
Don't worry if you don't know Svelte yet! You can ignore all the nice features SvelteKit brings on top for now and dive into it later.
### Alternatives to SvelteKit
If you don't want to use SvelteKit for some reason, you can also use Svelte with Vite (but without SvelteKit) by running `npm create vite@latest` and selecting the `svelte` option. With this, `npm run build` will generate HTML, JS and CSS files inside the `dist` directory. In most cases, you will probably need to [choose a routing library](/faq#is-there-a-router) as well.
If you don't want to use SvelteKit for some reason, you can also use Svelte with Vite (but without SvelteKit) by running `npm create vite@latest` and selecting the `svelte` option. With this, `npm run build` will generate HTML, JS and CSS files inside the `dist` directory thanks using [vite-plugin-svelte](https://github.com/sveltejs/vite-plugin-svelte). In most cases, you will probably need to [choose a routing library](faq#is-there-a-router) as well.
Alternatively, there are [plugins for all the major web bundlers](https://sveltesociety.dev/tools#bundling) to handle Svelte compilation — which will output `.js` and `.css` that you can insert into your HTML — but most others won't handle SSR.
Alternatively, there are plugins for [Rollup](https://github.com/sveltejs/rollup-plugin-svelte), [Webpack](https://github.com/sveltejs/svelte-loader) [and a few others](https://sveltesociety.dev/packages?category=build-plugins) to handle Svelte compilation — which will output `.js` and `.css` that you can insert into your HTML — but setting up SSR with them requires more manual work.
## Editor tooling
The Svelte team maintains a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) and there are integrations with various other [editors](https://sveltesociety.dev/tools#editor-support) and tools as well.
The Svelte team maintains a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) and there are integrations with various other [editors](https://sveltesociety.dev/resources#editor-support) and tools as well.
You can also check your code from the command line using [svelte-check](https://www.npmjs.com/package/svelte-check) (using the Svelte or Vite CLI setup will install this for you).
## Getting help

@ -0,0 +1,88 @@
---
title: Reactivity fundamentals
---
Reactivity is at the heart of interactive UIs. When you click a button, you expect some kind of response. It's your job as a developer to make this happen. It's Svelte's job to make your job as intuitive as possible, by providing a good API to express reactive systems.
## Runes
Svelte 5 uses _runes_, a powerful set of primitives for controlling reactivity inside your Svelte components and inside `.svelte.js` and `.svelte.ts` modules.
Runes are function-like symbols that provide instructions to the Svelte compiler. You don't need to import them from anywhere — when you use Svelte, they're part of the language.
The following sections introduce the most important runes for declare state, derived state and side effects at a high level. For more details refer to the later sections on [state](/docs/svelte/runes/state) and [side effects](/docs/svelte/runes/side-effects).
## `$state`
Reactive state is declared with the `$state` rune:
```svelte
<script>
let count = $state(0);
</script>
<button onclick={() => count++}>
clicks: {count}
</button>
```
You can also use `$state` in class fields (whether public or private):
```js
// @errors: 7006 2554
class Todo {
done = $state(false);
text = $state();
constructor(text) {
this.text = text;
}
}
```
## `$derived`
Derived state is declared with the `$derived` rune:
```svelte
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<button onclick={() => count++}>
{doubled}
</button>
<p>{count} doubled is {doubled}</p>
```
The expression inside `$derived(...)` should be free of side-effects. Svelte will disallow state changes (e.g. `count++`) inside derived expressions.
As with `$state`, you can mark class fields as `$derived`.
## `$effect`
To run _side-effects_ when the component is mounted to the DOM, and when values change, we can use the `$effect` rune ([demo](/#H4sIAAAAAAAAE31T24rbMBD9lUG7kAQ2sbdlX7xOYNk_aB_rQhRpbAsU2UiTW0P-vbrYubSlYGzmzMzROTPymdVKo2PFjzMzfIusYB99z14YnfoQuD1qQh-7bmdFQEonrOppVZmKNBI49QthCc-OOOH0LZ-9jxnR6c7eUpOnuv6KeT5JFdcqbvbcBcgDz1jXKGg6ncFyBedYR6IzLrAZwiN5vtSxaJA-EzadfJEjKw11C6GR22-BLH8B_wxdByWpvUYtqqal2XB6RVkG1CoHB6U1WJzbnYFDiwb3aGEdDa3Bm1oH12sQLTcNPp7r56m_00mHocSG97_zd7ICUXonA5fwKbPbkE2ZtMJGGVkEdctzQi4QzSwr9prnFYNk5hpmqVuqPQjNnfOJoMF22lUsrq_UfIN6lfSVyvQ7grB3X2mjMZYO3XO9w-U5iLx42qg29md3BP_ni5P4gy9ikTBlHxjLzAtPDlyYZmRdjAbGq7HprEQ7p64v4LU_guu0kvAkhBim3nMplWl8FreQD-CW20aZR0wq12t-KqDWeBywhvexKC3memmDwlHAv9q4Vo2ZK8KtK0CgX7u9J8wXbzdKv-nRnfF_2baTqlYoWUF2h5efl9-n0O6koAMAAA==)):
```svelte
<script>
let size = $state(50);
let color = $state('#ff3e00');
let canvas;
$effect(() => {
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
// this will re-run whenever `color` or `size` change
context.fillStyle = color;
context.fillRect(0, 0, size, size);
});
</script>
<canvas bind:this={canvas} width="100" height="100" />
```
The function passed to `$effect` will run when the component mounts, and will re-run after any changes to the values it reads that were declared with `$state` or `$derived` (including those passed in with `$props`). Re-runs are batched (i.e. changing `color` and `size` in the same moment won't cause two separate runs), and happen after any DOM updates have been applied.

@ -0,0 +1,3 @@
---
title: Introduction
---

@ -0,0 +1,184 @@
---
title: Component fundamentals
---
- script (module) / template / style (rough overview)
- `$props` / `$state` (in the context of components)
Components are the building blocks of Svelte applications. They are written into `.svelte` files, using a superset of HTML.
All three sections — script, styles and markup — are optional.
```svelte
<script>
// logic goes here
</script>
<!-- markup (zero or more items) goes here -->
<style>
/* styles go here */
</style>
```
## &lt;script&gt;
A `<script>` block contains JavaScript (or TypeScript, when adding the `lang="ts"` attribute) that runs when a component instance is created. Variables declared (or imported) at the top level are 'visible' from the component's markup.
### Public API of a component
Svelte uses the `$props` rune to declare _properties_ or _props_, which means describing the public interface of the component which becomes accessible to consumers of the component.
> `$props` is one of several runes, which are special hints for Svelte's compiler to make things reactive.
```svelte
<script>
let { foo, bar, baz } = $props();
// Values that are passed in as props
// are immediately available
console.log({ foo, bar, baz });
</script>
```
You can specify a fallback value for a prop. It will be used if the component's consumer doesn't specify the prop on the component when instantiating the component, or if the passed value is `undefined` at some point.
```svelte
<script>
let { foo = 'optional default initial value' } = $props();
</script>
```
To get all properties, use rest syntax:
```svelte
<script>
let { a, b, c, ...everythingElse } = $props();
</script>
```
You can use reserved words as prop names.
```svelte
<script>
// creates a `class` property, even
// though it is a reserved word
let { class: className } = $props();
</script>
```
If you're using TypeScript, you can declare the prop types:
```svelte
<script lang="ts">
interface Props {
a: number;
b: boolean;
c: string;
[key: string]: unknown;
}
let { a, b, c, ...everythingElse }: Props = $props();
</script>
```
If you export a `const`, `class` or `function`, it is readonly from outside the component.
```svelte
<script>
export const thisIs = 'readonly';
export function greet(name) {
alert(`hello ${name}!`);
}
</script>
```
Readonly props can be accessed as properties on the element, tied to the component using [`bind:this` syntax](/docs/component-directives#bind-this).
### Reactive variables
To change component state and trigger a re-render, just assign to a locally declared variable that was declared using the `$state` rune.
Update expressions (`count += 1`) and property assignments (`obj.x = y`) have the same effect.
```svelte
<script>
let count = $state(0);
function handleClick() {
// calling this function will trigger an
// update if the markup references `count`
count = count + 1;
}
</script>
```
Svelte's `<script>` blocks are run only when the component is created, so assignments within a `<script>` block are not automatically run again when a prop updates.
```svelte
<script>
let { person } = $props();
// this will only set `name` on component creation
// it will not update when `person` does
let { name } = person;
</script>
```
If you'd like to react to changes to a prop, use the `$derived` or `$effect` runes instead.
```svelte
<script>
let count = $state(0);
let double = $derived(count * 2);
$effect(() => {
if (count > 10) {
alert('Too high!');
}
});
</script>
```
For more information on reactivity, read the documentation around runes.
## &lt;script context="module"&gt;
A `<script>` tag with a `context="module"` attribute runs once when the module first evaluates, rather than for each component instance. Values declared in this block are accessible from a regular `<script>` (and the component markup) but not vice versa.
You can `export` bindings from this block, and they will become exports of the compiled module.
You cannot `export default`, since the default export is the component itself.
```svelte
<script context="module">
let totalComponents = 0;
// the export keyword allows this function to imported with e.g.
// `import Example, { alertTotal } from './Example.svelte'`
export function alertTotal() {
alert(totalComponents);
}
</script>
<script>
totalComponents += 1;
console.log(`total number of times this component has been created: ${totalComponents}`);
</script>
```
## &lt;style&gt;
CSS inside a `<style>` block will be scoped to that component.
```svelte
<style>
p {
/* this will only affect <p> elements in this component */
color: burlywood;
}
</style>
```
For more information regarding styling, read the documentation around [styles and classes](styles-and-classes).

@ -1,350 +0,0 @@
---
title: Svelte components
---
Components are the building blocks of Svelte applications. They are written into `.svelte` files, using a superset of HTML.
All three sections — script, styles and markup — are optional.
```svelte
<script>
// logic goes here
</script>
<!-- markup (zero or more items) goes here -->
<style>
/* styles go here */
</style>
```
## &lt;script&gt;
A `<script>` block contains JavaScript that runs when a component instance is created. Variables declared (or imported) at the top level are 'visible' from the component's markup. There are four additional rules:
### 1. `export` creates a component prop
Svelte uses the `export` keyword to mark a variable declaration as a _property_ or _prop_, which means it becomes accessible to consumers of the component (see the section on [attributes and props](/docs/basic-markup#attributes-and-props) for more information).
```svelte
<script>
export let foo;
// Values that are passed in as props
// are immediately available
console.log({ foo });
</script>
```
You can specify a default initial value for a prop. It will be used if the component's consumer doesn't specify the prop on the component (or if its initial value is `undefined`) when instantiating the component. Note that if the values of props are subsequently updated, then any prop whose value is not specified will be set to `undefined` (rather than its initial value).
In development mode (see the [compiler options](/docs/svelte-compiler#compile)), a warning will be printed if no default initial value is provided and the consumer does not specify a value. To squelch this warning, ensure that a default initial value is specified, even if it is `undefined`.
```svelte
<script>
export let bar = 'optional default initial value';
export let baz = undefined;
</script>
```
If you export a `const`, `class` or `function`, it is readonly from outside the component. Functions are valid prop values, however, as shown below.
```svelte
<!--- file: App.svelte --->
<script>
// these are readonly
export const thisIs = 'readonly';
/** @param {string} name */
export function greet(name) {
alert(`hello ${name}!`);
}
// this is a prop
export let format = (n) => n.toFixed(2);
</script>
```
Readonly props can be accessed as properties on the element, tied to the component using [`bind:this` syntax](/docs/component-directives#bind-this).
You can use reserved words as prop names.
```svelte
<!--- file: App.svelte --->
<script>
/** @type {string} */
let className;
// creates a `class` property, even
// though it is a reserved word
export { className as class };
</script>
```
### 2. Assignments are 'reactive'
To change component state and trigger a re-render, just assign to a locally declared variable.
Update expressions (`count += 1`) and property assignments (`obj.x = y`) have the same effect.
```svelte
<script>
let count = 0;
function handleClick() {
// calling this function will trigger an
// update if the markup references `count`
count = count + 1;
}
</script>
```
Because Svelte's reactivity is based on assignments, using array methods like `.push()` and `.splice()` won't automatically trigger updates. A subsequent assignment is required to trigger the update. This and more details can also be found in the [tutorial](https://learn.svelte.dev/tutorial/updating-arrays-and-objects).
```svelte
<script>
let arr = [0, 1];
function handleClick() {
// this method call does not trigger an update
arr.push(2);
// this assignment will trigger an update
// if the markup references `arr`
arr = arr;
}
</script>
```
Svelte's `<script>` blocks are run only when the component is created, so assignments within a `<script>` block are not automatically run again when a prop updates. If you'd like to track changes to a prop, see the next example in the following section.
```svelte
<script>
export let person;
// this will only set `name` on component creation
// it will not update when `person` does
let { name } = person;
</script>
```
### 3. `$:` marks a statement as reactive
Any top-level statement (i.e. not inside a block or a function) can be made reactive by prefixing it with the `$:` [JS label syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label). Reactive statements run after other script code and before the component markup is rendered, whenever the values that they depend on have changed.
```svelte
<script>
export let title;
export let person;
// this will update `document.title` whenever
// the `title` prop changes
$: document.title = title;
$: {
console.log(`multiple statements can be combined`);
console.log(`the current title is ${title}`);
}
// this will update `name` when 'person' changes
$: ({ name } = person);
// don't do this. it will run before the previous line
let name2 = name;
</script>
```
Only values which directly appear within the `$:` block will become dependencies of the reactive statement. For example, in the code below `total` will only update when `x` changes, but not `y`.
```svelte
<!--- file: App.svelte --->
<script>
let x = 0;
let y = 0;
/** @param {number} value */
function yPlusAValue(value) {
return value + y;
}
$: total = yPlusAValue(x);
</script>
Total: {total}
<button on:click={() => x++}> Increment X </button>
<button on:click={() => y++}> Increment Y </button>
```
It is important to note that the reactive blocks are ordered via simple static analysis at compile time, and all the compiler looks at are the variables that are assigned to and used within the block itself, not in any functions called by them. This means that `yDependent` will not be updated when `x` is updated in the following example:
```svelte
<script>
let x = 0;
let y = 0;
/** @param {number} value */
function setY(value) {
y = value;
}
$: yDependent = y;
$: setY(x);
</script>
```
Moving the line `$: yDependent = y` below `$: setY(x)` will cause `yDependent` to be updated when `x` is updated.
If a statement consists entirely of an assignment to an undeclared variable, Svelte will inject a `let` declaration on your behalf.
```svelte
<!--- file: App.svelte --->
<script>
/** @type {number} */
export let num;
// we don't need to declare `squared` and `cubed`
// — Svelte does it for us
$: squared = num * num;
$: cubed = squared * num;
</script>
```
### 4. Prefix stores with `$` to access their values
A _store_ is an object that allows reactive access to a value via a simple _store contract_. The [`svelte/store` module](/docs/svelte-store) contains minimal store implementations which fulfil this contract.
Any time you have a reference to a store, you can access its value inside a component by prefixing it with the `$` character. This causes Svelte to declare the prefixed variable, subscribe to the store at component initialisation and unsubscribe when appropriate.
Assignments to `$`-prefixed variables require that the variable be a writable store, and will result in a call to the store's `.set` method.
Note that the store must be declared at the top level of the component — not inside an `if` block or a function, for example.
Local variables (that do not represent store values) must _not_ have a `$` prefix.
```svelte
<script>
import { writable } from 'svelte/store';
const count = writable(0);
console.log($count); // logs 0
count.set(1);
console.log($count); // logs 1
$count = 2;
console.log($count); // logs 2
</script>
```
#### Store contract
```ts
// @noErrors
store = { subscribe: (subscription: (value: any) => void) => (() => void), set?: (value: any) => void }
```
You can create your own stores without relying on [`svelte/store`](/docs/svelte-store), by implementing the _store contract_:
1. A store must contain a `.subscribe` method, which must accept as its argument a subscription function. This subscription function must be immediately and synchronously called with the store's current value upon calling `.subscribe`. All of a store's active subscription functions must later be synchronously called whenever the store's value changes.
2. The `.subscribe` method must return an unsubscribe function. Calling an unsubscribe function must stop its subscription, and its corresponding subscription function must not be called again by the store.
3. A store may _optionally_ contain a `.set` method, which must accept as its argument a new value for the store, and which synchronously calls all of the store's active subscription functions. Such a store is called a _writable store_.
For interoperability with RxJS Observables, the `.subscribe` method is also allowed to return an object with an `.unsubscribe` method, rather than return the unsubscription function directly. Note however that unless `.subscribe` synchronously calls the subscription (which is not required by the Observable spec), Svelte will see the value of the store as `undefined` until it does.
## &lt;script context="module"&gt;
A `<script>` tag with a `context="module"` attribute runs once when the module first evaluates, rather than for each component instance. Values declared in this block are accessible from a regular `<script>` (and the component markup) but not vice versa.
You can `export` bindings from this block, and they will become exports of the compiled module.
You cannot `export default`, since the default export is the component itself.
> Variables defined in `module` scripts are not reactive — reassigning them will not trigger a rerender even though the variable itself will update. For values shared between multiple components, consider using a [store](/docs/svelte-store).
```svelte
<script context="module">
let totalComponents = 0;
// the export keyword allows this function to imported with e.g.
// `import Example, { alertTotal } from './Example.svelte'`
export function alertTotal() {
alert(totalComponents);
}
</script>
<script>
totalComponents += 1;
console.log(`total number of times this component has been created: ${totalComponents}`);
</script>
```
## &lt;style&gt;
CSS inside a `<style>` block will be scoped to that component.
This works by adding a class to affected elements, which is based on a hash of the component styles (e.g. `svelte-123xyz`).
```svelte
<style>
p {
/* this will only affect <p> elements in this component */
color: burlywood;
}
</style>
```
To apply styles to a selector globally, use the `:global(...)` modifier.
```svelte
<style>
:global(body) {
/* this will apply to <body> */
margin: 0;
}
div :global(strong) {
/* this will apply to all <strong> elements, in any
component, that are inside <div> elements belonging
to this component */
color: goldenrod;
}
p:global(.red) {
/* this will apply to all <p> elements belonging to this
component with a class of red, even if class="red" does
not initially appear in the markup, and is instead
added at runtime. This is useful when the class
of the element is dynamically applied, for instance
when updating the element's classList property directly. */
}
</style>
```
If you want to make @keyframes that are accessible globally, you need to prepend your keyframe names with `-global-`.
The `-global-` part will be removed when compiled, and the keyframe will then be referenced using just `my-animation-name` elsewhere in your code.
```svelte
<style>
@keyframes -global-my-animation-name {
/* code goes here */
}
</style>
```
There should only be 1 top-level `<style>` tag per component.
However, it is possible to have a `<style>` tag nested inside other elements or logic blocks.
In that case, the `<style>` tag will be inserted as-is into the DOM; no scoping or processing will be done on the `<style>` tag.
```svelte
<div>
<style>
/* this style tag will be inserted as-is */
div {
/* this will apply to all `<div>` elements in the DOM */
color: red;
}
</style>
</div>
```

@ -2,6 +2,8 @@
title: Basic markup
---
- [basically what we have in the Svelte docs today](https://svelte.dev/docs/basic-markup)
## Tags
A lowercase tag, like `<div>`, denotes a regular HTML element. A capitalised tag, such as `<Widget>` or `<Namespace.Widget>`, indicates a _component_.
@ -54,7 +56,7 @@ All other attributes are included unless their value is [nullish](https://develo
<div title={null}>This div has no title attribute</div>
```
An expression might include characters that would cause syntax highlighting to fail in regular HTML, so quoting the value is permitted. The quotes do not affect how the value is parsed:
Quoting a singular expression does not affect how the value is parsed yet, but in Svelte 6 it will:
<!-- prettier-ignore -->
```svelte
@ -86,23 +88,62 @@ An element or component can have multiple spread attributes, interspersed with r
<Widget {...things} />
```
`$$props` references all props that are passed to a component, including ones that are not declared with `export`. Using `$$props` will not perform as well as references to a specific prop because changes to any prop will cause Svelte to recheck all usages of `$$props`. But it can be useful in some cases for example, when you don't know at compile time what props might be passed to a component.
> The `value` attribute of an `input` element or its children `option` elements must not be set with spread attributes when using `bind:group` or `bind:checked`. Svelte needs to be able to see the element's `value` directly in the markup in these cases so that it can link it to the bound variable.
```svelte
<Widget {...$$props} />
```
> Sometimes, the attribute order matters as Svelte sets attributes sequentially in JavaScript. For example, `<input type="range" min="0" max="1" value={0.5} step="0.1"/>`, Svelte will attempt to set the value to `1` (rounding up from 0.5 as the step by default is 1), and then set the step to `0.1`. To fix this, change it to `<input type="range" min="0" max="1" step="0.1" value={0.5}/>`.
> Another example is `<img src="..." loading="lazy" />`. Svelte will set the img `src` before making the img element `loading="lazy"`, which is probably too late. Change this to `<img loading="lazy" src="...">` to make the image lazily loaded.
`$$restProps` contains only the props which are _not_ declared with `export`. It can be used to pass down other unknown attributes to an element in a component. It shares the same performance characteristics compared to specific property access as `$$props`.
## Events
Listening to DOM events is possible by adding attributes to the element that start with `on`. For example, to listen to the `click` event, add the `onclick` attribute to a button:
```svelte
<input {...$$restProps} />
<button onclick={() => console.log('clicked')}>click me</button>
```
> The `value` attribute of an `input` element or its children `option` elements must not be set with spread attributes when using `bind:group` or `bind:checked`. Svelte needs to be able to see the element's `value` directly in the markup in these cases so that it can link it to the bound variable.
Event attributes are case sensitive. `onclick` listens to the `click` event, `onClick` listens to the `Click` event, which is different. This ensures you can listen to custom events that have uppercase characters in them.
> Sometimes, the attribute order matters as Svelte sets attributes sequentially in JavaScript. For example, `<input type="range" min="0" max="1" value={0.5} step="0.1"/>`, Svelte will attempt to set the value to `1` (rounding up from 0.5 as the step by default is 1), and then set the step to `0.1`. To fix this, change it to `<input type="range" min="0" max="1" step="0.1" value={0.5}/>`.
Because events are just attributes, the same rules as for attributes apply:
> Another example is `<img src="..." loading="lazy" />`. Svelte will set the img `src` before making the img element `loading="lazy"`, which is probably too late. Change this to `<img loading="lazy" src="...">` to make the image lazily loaded.
- you can use the shorthand form: `<button {onclick}>click me</button>`
- you can spread them: `<button {...thisSpreadContainsEventAttributes}>click me</button>`
- component events are just (callback) properties and don't need a separate concept
### Event delegation
To reduce the memory footprint and increase performance, Svelte uses a technique called event delegation. This means that certain events are only listened to once at the application root, invoking a handler that then traverses the event call path and invokes listeners along the way.
There are a few gotchas you need to be aware of when it comes to event delegation:
- when you dispatch events manually, make sure to set the `{ bubbles: true }` option
- when listening to events programmatically (i.e. not through `<button onclick={...}>` but through `node.addEventListener`), be careful to not call `stopPropagation` or else the delegated event handler won't be reached and handlers won't be invoked. For this reaon it's best to use `on` (which properly handles `stopPropagation`) from `svelte/events` instead of `addEventListener` to make sure the chain of events is preserved
The following events are delegated:
- `beforeinput`
- `click`
- `change`
- `dblclick`
- `contextmenu`
- `focusin`
- `focusout`
- `input`
- `keydown`
- `keyup`
- `mousedown`
- `mousemove`
- `mouseout`
- `mouseover`
- `mouseup`
- `pointerdown`
- `pointermove`
- `pointerout`
- `pointerover`
- `pointerup`
- `touchend`
- `touchmove`
- `touchstart`
## Text expressions
@ -114,7 +155,7 @@ A JavaScript expression can be included as text by surrounding it with curly bra
Curly braces can be included in a Svelte template by using their [HTML entity](https://developer.mozilla.org/docs/Glossary/Entity) strings: `&lbrace;`, `&lcub;`, or `&#123;` for `{` and `&rbrace;`, `&rcub;`, or `&#125;` for `}`.
> If you're using a regular expression (`RegExp`) [literal notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#literal_notation_and_constructor), you'll need to wrap it in parentheses.
If you're using a regular expression (`RegExp`) [literal notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#literal_notation_and_constructor), you'll need to wrap it in parentheses.
<!-- prettier-ignore -->
```svelte
@ -124,6 +165,14 @@ Curly braces can be included in a Svelte template by using their [HTML entity](h
<div>{(/^[A-Za-z ]+$/).test(value) ? x : y}</div>
```
The expression will be stringified and escaped to prevent code injections. If you want to render HTML, use the `{@html}` tag instead.
```svelte
{@html potentiallyUnsafeHtmlString}
```
> Make sure that you either escape the passed string or only populate it with values that are under your control in order to prevent [XSS attacks](https://owasp.org/www-community/attacks/xss/)
## Comments
You can use HTML comments inside components.
@ -138,3 +187,26 @@ Comments beginning with `svelte-ignore` disable warnings for the next block of m
<!-- svelte-ignore a11y-autofocus -->
<input bind:value={name} autofocus />
```
You can add a special comment starting with `@component` that will show up when hovering over the component name in other files.
````svelte
<!--
@component
- You can use markdown here.
- You can also use code blocks here.
- Usage:
```html
<Main name="Arethra">
```
-->
<script>
let { name } = $props();
</script>
<main>
<h1>
Hello, {name}
</h1>
</main>
````

@ -1,7 +1,20 @@
---
title: Logic blocks
title: Control flow
---
- if
- each
- await (or move that into some kind of data loading section?)
- NOT: key (move into transition section, because that's the common use case)
Svelte augments HTML with control flow blocks to be able to express conditionally rendered content or lists.
The syntax between these blocks is the same:
- `{#` denotes the start of a block
- `{:` denotes a different branch part of the block. Depending on the block, there can be multiple of these
- `{/` denotes the end of a block
## {#if ...}
```svelte
@ -128,96 +141,8 @@ An each block can also have an `{:else}` clause, which is rendered if the list i
{/each}
```
Since Svelte 4 it is possible to iterate over iterables like `Map` or `Set`. Iterables need to be finite and static (they shouldn't change while being iterated over). Under the hood, they are transformed to an array using `Array.from` before being passed off to rendering. If you're writing performance-sensitive code, try to avoid iterables and use regular arrays as they are more performant.
## {#await ...}
```svelte
<!--- copy: false --->
{#await expression}...{:then name}...{:catch name}...{/await}
```
```svelte
<!--- copy: false --->
{#await expression}...{:then name}...{/await}
```
```svelte
<!--- copy: false --->
{#await expression then name}...{/await}
```
```svelte
<!--- copy: false --->
{#await expression catch name}...{/await}
```
Await blocks allow you to branch on the three possible states of a Promise — pending, fulfilled or rejected.
In SSR mode, only the pending branch will be rendered on the server.
If the provided expression is not a Promise only the fulfilled branch will be rendered, including in SSR mode.
```svelte
{#await promise}
<!-- promise is pending -->
<p>waiting for the promise to resolve...</p>
{:then value}
<!-- promise was fulfilled or not a Promise -->
<p>The value is {value}</p>
{:catch error}
<!-- promise was rejected -->
<p>Something went wrong: {error.message}</p>
{/await}
```
It is possible to iterate over iterables like `Map` or `Set`. Iterables need to be finite and static (they shouldn't change while being iterated over). Under the hood, they are transformed to an array using `Array.from` before being passed off to rendering. If you're writing performance-sensitive code, try to avoid iterables and use regular arrays as they are more performant.
The `catch` block can be omitted if you don't need to render anything when the promise rejects (or no error is possible).
## Other block types
```svelte
{#await promise}
<!-- promise is pending -->
<p>waiting for the promise to resolve...</p>
{:then value}
<!-- promise was fulfilled -->
<p>The value is {value}</p>
{/await}
```
If you don't care about the pending state, you can also omit the initial block.
```svelte
{#await promise then value}
<p>The value is {value}</p>
{/await}
```
Similarly, if you only want to show the error state, you can omit the `then` block.
```svelte
{#await promise catch error}
<p>The error is {error}</p>
{/await}
```
## {#key ...}
```svelte
<!--- copy: false --->
{#key expression}...{/key}
```
Key blocks destroy and recreate their contents when the value of an expression changes.
This is useful if you want an element to play its transition whenever a value changes.
```svelte
{#key value}
<div transition:fade>{value}</div>
{/key}
```
When used around components, this will cause them to be reinstantiated and reinitialised.
```svelte
{#key value}
<Component />
{/key}
```
Svelte also provides [`#snippet`](snippets), [`#key`](transitions-and-animations) and [`#await`](data-fetching) blocks. You can find out more about them in their respective sections.

@ -0,0 +1,253 @@
---
title: Snippets
---
Better title needed?
- `#snippet`
- `@render`
- how they can be used to reuse markup
- how they can be used to pass UI content to components
Snippets, and _render tags_, are a way to create reusable chunks of markup inside your components. Instead of writing duplicative code like [this](/#H4sIAAAAAAAAE5VUYW-kIBD9K8Tmsm2yXXRzvQ-s3eR-R-0HqqOQKhAZb9sz_vdDkV1t000vRmHewMx7w2AflbIGG7GnPlK8gYhFv42JthG-m9Gwf6BGcLbVXZuPSGrzVho8ZirDGpDIhldgySN5GpEMez9kaNuckY1ANJZRamRuu2ZnhEZt6a84pvs43mzD4pMsUDDi8DMkQFYCGdkvsJwblFq5uCik9bmJ4JZwUkv1eoknWigX2eGNN6aGXa6bjV8ybP-X7sM36T58SVcrIIV2xVIaA41xeD5kKqWXuqpUJEefOqVuOkL9DfBchGrzWfu0vb-RpTd3o-zBR045Ga3HfuE5BmJpKauuhbPtENlUF2sqR9jqpsPSxWsMrlngyj3VJiyYjJXb1-lMa7IWC-iSk2M5Zzh-SJjShe-siq5kpZRPs55BbSGU5YPyte4vVV_VfFXxVb10dSLf17pS2lM5HnpPxw4Zpv6x-F57p0jI3OKlVnhv5V9wPQrNYQQ9D_f6aGHlC89fq1Z3qmDkJCTCweOGF4VUFSPJvD_DhreVdA0eu8ehJJ5x91dBaBkpWm3ureCFPt3uzRv56d4kdp-2euG38XZ6dsnd3ZmPG9yRBCrzRUvi-MccOdwz3qE-fOZ7AwAhlrtTUx3c76vRhSwlFBHDtoPhefgHX3dM0PkEAAA=)...
```svelte
{#each images as image}
{#if image.href}
<a href={image.href}>
<figure>
<img src={image.src} alt={image.caption} width={image.width} height={image.height} />
<figcaption>{image.caption}</figcaption>
</figure>
</a>
{:else}
<figure>
<img src={image.src} alt={image.caption} width={image.width} height={image.height} />
<figcaption>{image.caption}</figcaption>
</figure>
{/if}
{/each}
```
...you can write [this](/#H4sIAAAAAAAAE5VUYW-bMBD9KxbRlERKY4jWfSA02n5H6QcXDmwVbMs-lnaI_z6D7TTt1moTAnPvzvfenQ_GpBEd2CS_HxPJekjy5IfWyS7BFz0b9id0CM62ajDVjBS2MkLjqZQldoBE9KwFS-7I_YyUOPqlRGuqnKw5orY5pVpUduj3mitUln5LU3pI0_UuBp9FjTwnDr9AHETLMSeHK6xiGoWSLi9yYT034cwSRjohn17zcQPNFTs8s153sK9Uv_Yh0-5_5d7-o9zbD-UqCaRWrllSYZQxLw_HUhb0ta-y4NnJUxfUvc7QuLJSaO0a3oh2MLBZat8u-wsPnXzKQvTtVVF34xK5d69ThFmHEQ4SpzeVRediTG8rjD5vBSeN3E5JyHh6R1DQK9-iml5kjzQUN_lSgVU8DhYLx7wwjSvRkMDvTjiwF4zM1kXZ7DlF1eN3A7IG85e-zRrYEjjm0FkI4Cc7Ripm0pHOChexhcWXzreeZyRMU6Mk3ljxC9w4QH-cQZ_b3T5pjHxk1VNr1CDrnJy5QDh6XLO6FrLNSRb2l9gz0wo3S6m7HErSgLsPGMHkpDZK31jOanXeHPQz-eruLHUP0z6yTbpbrn223V70uMXNSpQSZjpL0y8hcxxpNqA6_ql3BQAxlxvfpQ_uT9GrWjQC6iRHM8D0MP0GQsIi92QEAAA=):
```svelte
{#snippet figure(image)}
<figure>
<img
src={image.src}
alt={image.caption}
width={image.width}
height={image.height}
/>
<figcaption>{image.caption}</figcaption>
</figure>
{/snippet}
{#each images as image}
{#if image.href}
<a href={image.href}>
{@render figure(image)}
</a>
{:else}
{@render figure(image)}
{/if}
{/each}
```
Like function declarations, snippets can have an arbitrary number of parameters, which can have default values, and you can destructure each parameter. You cannot use rest parameters however.
## Snippet scope
Snippets can be declared anywhere inside your component. They can reference values declared outside themselves, for example in the `<script>` tag or in `{#each ...}` blocks ([demo](/#H4sIAAAAAAAAE12P0QrCMAxFfyWrwhSEvc8p-h1OcG5RC10bmkyQ0n-3HQPBx3vCPUmCemiDrOpLULYbUdXqTKR2Sj6UA7_RCKbMbvJ9Jg33XpMcW9uKQYEAIzJ3T4QD3LSUDE-PnYA4YET4uOkGMc3W5B3xZrtvbVP9HDas2GqiZHqhMW6Tr9jGbG_oOCMImcUCwrIpFk1FqRyqpRpn0cmjHdAvnrIzuscyq_4nd3dPPD01ukE_NA6qFj9hvMYvGjJADw8BAAA=))...
```svelte
<script>
let { message = `it's great to see you!` } = $props();
</script>
{#snippet hello(name)}
<p>hello {name}! {message}!</p>
{/snippet}
{@render hello('alice')}
{@render hello('bob')}
```
...and they are 'visible' to everything in the same lexical scope (i.e. siblings, and children of those siblings):
```svelte
<div>
{#snippet x()}
{#snippet y()}...{/snippet}
<!-- this is fine -->
{@render y()}
{/snippet}
<!-- this will error, as `y` is not in scope -->
{@render y()}
</div>
<!-- this will also error, as `x` is not in scope -->
{@render x()}
```
Snippets can reference themselves and each other ([demo](/#H4sIAAAAAAAAE2WPTQqDMBCFrxLiRqH1Zysi7TlqF1YnENBJSGJLCYGeo5tesUeosfYH3c2bee_jjaWMd6BpfrAU6x5oTvdS0g01V-mFPkNnYNRaDKrxGxto5FKCIaeu1kYwFkauwsoUWtZYPh_3W5FMY4U2mb3egL9kIwY0rbhgiO-sDTgjSEqSTvIDs-jiOP7i_MHuFGAL6p9BtiSbOTl0GtzCuihqE87cqtyam6WRGz_vRcsZh5bmRg3gju4Fptq_kzQBAAA=)):
```svelte
{#snippet blastoff()}
<span>🚀</span>
{/snippet}
{#snippet countdown(n)}
{#if n > 0}
<span>{n}...</span>
{@render countdown(n - 1)}
{:else}
{@render blastoff()}
{/if}
{/snippet}
{@render countdown(10)}
```
## Passing snippets to components
Within the template, snippets are values just like any other. As such, they can be passed to components as props ([demo](/#H4sIAAAAAAAAE41SwY6bMBD9lRGplKQlYRMpF5ZF7T_0ttmDwSZYJbZrT9pGlv-9g4Fkk-xhxYV5vHlvhjc-aWQnXJK_-kSxo0jy5IcxSZrg2fSF-yM6FFQ7fbJ1jxSuttJguVd7lEejLcJPVnUCGquPMF9nsVoPjfNnohGx1sohMU4SHbzAa4_t0UNvmcOcGUNDzFP4jeccdikYK2v6sIWQ3lErpui5cDdPF_LmkVy3wlp5Vd5e2U_rHYSe_kYjFtl1KeVnTkljBEIrGBd2sYy8AtsyLlBk9DYhJHtTR_UbBDWybkR8NkqHWyOr_y74ZMNLz9f9AoG6ePkOJLMHLBp-xISvcPf11r0YUuMM2Ysfkgngh5XphUYKkJWU_FFz2UjBkxztSYT0cihR4LOn0tGaPrql439N-7Uh0Dl8MVYbt1jeJ1Fg7xDb_Uw2Y18YQqZ_S2U5FH1pS__dCkWMa3C0uR0pfQRTg89kE4bLLLDS_Dxy_Eywuo1TAnPAw4fqY1rvtH3W9w35ZZMgvU3jq8LhedwkguCHRhT_cMU6eVA5dKLB5wGutCWjlTOslupAxxrxceKoD2hzhe2qbmXHF1v1bbOcNCtW_zpYfVI8h5kQ4qY3mueHTlesW2C7TOEO4hcdwzgf3Nc7cZxUKKC4yuNhvIX_MlV_Xk0EAAA=)):
```svelte
<script>
import Table from './Table.svelte';
const fruits = [
{ name: 'apples', qty: 5, price: 2 },
{ name: 'bananas', qty: 10, price: 1 },
{ name: 'cherries', qty: 20, price: 0.5 }
];
</script>
{#snippet header()}
<th>fruit</th>
<th>qty</th>
<th>price</th>
<th>total</th>
{/snippet}
{#snippet row(d)}
<td>{d.name}</td>
<td>{d.qty}</td>
<td>{d.price}</td>
<td>{d.qty * d.price}</td>
{/snippet}
<Table data={fruits} {header} {row} />
```
Think about it like passing content instead of data to a component. The concept is similar to slots in web components.
As an authoring convenience, snippets declared directly _inside_ a component implicitly become props _on_ the component ([demo](/#H4sIAAAAAAAAE41Sy27bMBD8lYVcwHYrW4kBXxRFaP-htzgHSqQsojLJkuu2BqF_74qUrfhxCHQRh7MzO9z1SSM74ZL8zSeKHUSSJz-MSdIET2Y4uD-iQ0Fnp4-2HpDC1VYaLHdqh_JgtEX4yapOQGP1AebrLJzWsXD-QjQi1lo5JMZRooNXeBuwHXoYLHOYM2OoiXkKv_GUwzYFY2VNFxvo0xtqxRR9F-7z04X8fE-uW2GtnJQ3E_tpvYV-oL9Ti0U2hVJFjMMZslcfW-5DWj9zShojEFrBuLCLZR_9CmzLQCwy-psw8rxBgvkNhhpZd8F8NppE7Stbq_8u-GTKS8_XQ9Keqnl5BZP1AzTYP2bDV7i7_9hLEeda0iocNJeNFDzJ0R5Fn142JzA-uzsdBfLhldPxPdMhIPS0H1-M1cYtlnejwdBDfBXZjHXTFOg4BhuOtvTfrVDEmAZG2ew5ezYV-Ew2fVzVAivNTyPHzwSr29AlMAe8f6g-zuWDts-GusAmdBSkv3P7qnB4GpMEEHwsRPEPV6yTe5VDJxp8iXClLRmtnGG1VHva3oCPHQd9QJsrbFd1Kzu-2Khvz8uzZsXqX3urj4rnMBNCXNUG83zf6Yp1C2yXKdxA_KJjGOfRfb0Vh7MKDShEuV-M9_4_nq6svF4EAAA=)):
```svelte
<!-- this is semantically the same as the above -->
<Table data={fruits}>
{#snippet header()}
<th>fruit</th>
<th>qty</th>
<th>price</th>
<th>total</th>
{/snippet}
{#snippet row(d)}
<td>{d.name}</td>
<td>{d.qty}</td>
<td>{d.price}</td>
<td>{d.qty * d.price}</td>
{/snippet}
</Table>
```
Any content inside the component tags that is _not_ a snippet declaration implicitly becomes part of the `children` snippet ([demo](/#H4sIAAAAAAAAE41S247aMBD9lVFYCegGsiDxks1G7T_0bdkHJ3aI1cR27aEtsvzvtZ0LZeGhiiJ5js-cmTMemzS8YybJ320iSM-SPPmmVJImeFEhML9Yh8zHRp51HZDC1JorLI_iiLxXUiN8J1XHoNGyh-U2i9F2SFy-epon1lIY9IwzRwNv8B6wI1oIJXNYEqV8E8sUfuIlh0MKSvPaX-zBpZ-oFRH-m7m7l5m8uyfXLdOaX5X3V_bL9gAu0D98i0V2NSWKwQ4lSN7s0LKLbgtsyxgXmT9NiBe-iaP-DYISSTcj4bcLI7hSDEHL3yu6dkPfBdLS0m1o3nk-LW9gX-gBGss9ZsMXuLu32VjZBdfRaelft5eUN5zRJEd9Zi6dlyEy_ncdOm_IxsGlULe8o5qJNFgE5x_9SWmpzGp9N2-MXQxz4c2cOQ-lZWQyF0Jd2q_-mjI9U1fr4FBPE8iuKTbjjRt2sMBK0svIsQtG6jb2CsQAdQ_1x9f5R9tmIS-yPToK-tNkQRQGL6ObCIIdEpH9wQ3p-Enk0LEGXwe4ktoX2hhFai5Ofi0jPnYc9QF1LrDdRK-rvXjerSfNitQ_TlqeBc1hwRi7yY3F81MnK9KtsF2n8Amis44ilA7VtwfWTyr-kaKV-_X4cH8BTOhfRzcEAAA=)):
```svelte
<!--- file: App.svelte --->
<Button>click me<Button>
```
```svelte
<!--- file: Button.svelte --->
<script>
let { children } = $props();
</script>
<!-- result will be <button>click me</button> -->
<button>{@render children()}</button>
```
> Note that you cannot have a prop called `children` if you also have content inside the component — for this reason, you should avoid having props with that name
You can declare snippet props as being optional. You can either use optional chaining to not render anything if the snippet isn't set...
```svelte
<script>
let { children } = $props();
</script>
{@render children?.()}
```
...or use an `#if` block to render fallback content:
```svelte
<script>
let { children } = $props();
</script>
{#if children}
{@render children()}
{:else}
fallback content
{/if}
```
## Typing snippets
Snippets implement the `Snippet` interface imported from `'svelte'`:
```svelte
<script lang="ts">
import type { Snippet } from 'svelte';
interface Props {
data: any[];
children: Snippet;
row: Snippet<[any]>;
}
let { data, children, row }: Props = $props();
</script>
```
With this change, red squigglies will appear if you try and use the component without providing a `data` prop and a `row` snippet. Notice that the type argument provided to `Snippet` is a tuple, since snippets can have multiple parameters.
We can tighten things up further by declaring a generic, so that `data` and `row` refer to the same type:
```svelte
<script lang="ts" generics="T">
import type { Snippet } from 'svelte';
let {
data,
children,
row
}: {
data: T[];
children: Snippet;
row: Snippet<[T]>;
} = $props();
</script>
```
## Snippets and slots
In Svelte 4, content can be passed to components using [slots](https://svelte.dev/docs/special-elements#slot). Snippets are more powerful and flexible, and as such slots are deprecated in Svelte 5.

@ -1,88 +0,0 @@
---
title: Special tags
---
## {@html ...}
```svelte
<!--- copy: false --->
{@html expression}
```
In a text expression, characters like `<` and `>` are escaped; however, with HTML expressions, they're not.
The expression should be valid standalone HTML — `{@html "<div>"}content{@html "</div>"}` will _not_ work, because `</div>` is not valid HTML. It also will _not_ compile Svelte code.
> Svelte does not sanitize expressions before injecting HTML. If the data comes from an untrusted source, you must sanitize it, or you are exposing your users to an XSS vulnerability.
```svelte
<div class="blog-post">
<h1>{post.title}</h1>
{@html post.content}
</div>
```
## {@debug ...}
```svelte
<!--- copy: false --->
{@debug}
```
```svelte
<!--- copy: false --->
{@debug var1, var2, ..., varN}
```
The `{@debug ...}` tag offers an alternative to `console.log(...)`. It logs the values of specific variables whenever they change, and pauses code execution if you have devtools open.
```svelte
<script>
let user = {
firstname: 'Ada',
lastname: 'Lovelace'
};
</script>
{@debug user}
<h1>Hello {user.firstname}!</h1>
```
`{@debug ...}` accepts a comma-separated list of variable names (not arbitrary expressions).
```svelte
<!-- Compiles -->
{@debug user}
{@debug user1, user2, user3}
<!-- WON'T compile -->
{@debug user.firstname}
{@debug myArray[0]}
{@debug !isReady}
{@debug typeof user === 'object'}
```
The `{@debug}` tag without any arguments will insert a `debugger` statement that gets triggered when _any_ state changes, as opposed to the specified variables.
## {@const ...}
```svelte
<!--- copy: false --->
{@const assignment}
```
The `{@const ...}` tag defines a local constant.
```svelte
<script>
export let boxes;
</script>
{#each boxes as box}
{@const area = box.width * box.height}
{box.width} * {box.height} = {area}
{/each}
```
`{@const}` is only allowed as direct child of `{#if}`, `{:else if}`, `{:else}`, `{#each}`, `{:then}`, `{:catch}`, `<Component />` or `<svelte:fragment />`.

@ -1,863 +0,0 @@
---
title: Element directives
---
As well as attributes, elements can have _directives_, which control the element's behaviour in some way.
## on:_eventname_
```svelte
<!--- copy: false --->
on:eventname={handler}
```
```svelte
<!--- copy: false --->
on:eventname|modifiers={handler}
```
Use the `on:` directive to listen to DOM events.
```svelte
<!--- file: App.svelte --->
<script>
let count = 0;
/** @param {MouseEvent} event */
function handleClick(event) {
count += 1;
}
</script>
<button on:click={handleClick}>
count: {count}
</button>
```
Handlers can be declared inline with no performance penalty. As with attributes, directive values may be quoted for the sake of syntax highlighters.
```svelte
<button on:click={() => (count += 1)}>
count: {count}
</button>
```
Add _modifiers_ to DOM events with the `|` character.
```svelte
<form on:submit|preventDefault={handleSubmit}>
<!-- the `submit` event's default is prevented,
so the page won't reload -->
</form>
```
The following modifiers are available:
- `preventDefault` — calls `event.preventDefault()` before running the handler
- `stopPropagation` — calls `event.stopPropagation()`, preventing the event reaching the next element
- `stopImmediatePropagation` - calls `event.stopImmediatePropagation()`, preventing other listeners of the same event from being fired.
- `passive` — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so)
- `nonpassive` — explicitly set `passive: false`
- `capture` — fires the handler during the _capture_ phase instead of the _bubbling_ phase
- `once` — remove the handler after the first time it runs
- `self` — only trigger handler if `event.target` is the element itself
- `trusted` — only trigger handler if `event.isTrusted` is `true`. I.e. if the event is triggered by a user action.
Modifiers can be chained together, e.g. `on:click|once|capture={...}`.
If the `on:` directive is used without a value, the component will _forward_ the event, meaning that a consumer of the component can listen for it.
```svelte
<button on:click> The component itself will emit the click event </button>
```
It's possible to have multiple event listeners for the same event:
```svelte
<script>
let counter = 0;
function increment() {
counter = counter + 1;
}
/** @param {MouseEvent} event */
function track(event) {
trackEvent(event);
}
</script>
<button on:click={increment} on:click={track}>Click me!</button>
```
## bind:_property_
```svelte
<!--- copy: false --->
bind:property={variable}
```
Data ordinarily flows down, from parent to child. The `bind:` directive allows data to flow the other way, from child to parent. Most bindings are specific to particular elements.
The simplest bindings reflect the value of a property, such as `input.value`.
```svelte
<input bind:value={name} />
<textarea bind:value={text} />
<input type="checkbox" bind:checked={yes} />
```
If the name matches the value, you can use a shorthand.
```svelte
<input bind:value />
<!-- equivalent to
<input bind:value={value} />
-->
```
Numeric input values are coerced; even though `input.value` is a string as far as the DOM is concerned, Svelte will treat it as a number. If the input is empty or invalid (in the case of `type="number"`), the value is `undefined`.
```svelte
<input type="number" bind:value={num} />
<input type="range" bind:value={num} />
```
On `<input>` elements with `type="file"`, you can use `bind:files` to get the [`FileList` of selected files](https://developer.mozilla.org/en-US/docs/Web/API/FileList). It is readonly.
```svelte
<label for="avatar">Upload a picture:</label>
<input accept="image/png, image/jpeg" bind:files id="avatar" name="avatar" type="file" />
```
If you're using `bind:` directives together with `on:` directives, the order that they're defined in affects the value of the bound variable when the event handler is called.
```svelte
<script>
let value = 'Hello World';
</script>
<input
on:input={() => console.log('Old value:', value)}
bind:value
on:input={() => console.log('New value:', value)}
/>
```
Here we were binding to the value of a text input, which uses the `input` event. Bindings on other elements may use different events such as `change`.
## Binding `<select>` value
A `<select>` value binding corresponds to the `value` property on the selected `<option>`, which can be any value (not just strings, as is normally the case in the DOM).
```svelte
<select bind:value={selected}>
<option value={a}>a</option>
<option value={b}>b</option>
<option value={c}>c</option>
</select>
```
A `<select multiple>` element behaves similarly to a checkbox group. The bound variable is an array with an entry corresponding to the `value` property of each selected `<option>`.
```svelte
<select multiple bind:value={fillings}>
<option value="Rice">Rice</option>
<option value="Beans">Beans</option>
<option value="Cheese">Cheese</option>
<option value="Guac (extra)">Guac (extra)</option>
</select>
```
When the value of an `<option>` matches its text content, the attribute can be omitted.
```svelte
<select multiple bind:value={fillings}>
<option>Rice</option>
<option>Beans</option>
<option>Cheese</option>
<option>Guac (extra)</option>
</select>
```
Elements with the `contenteditable` attribute support the following bindings:
- [`innerHTML`](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML)
- [`innerText`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText)
- [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
There are slight differences between each of these, read more about them [here](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent#Differences_from_innerText).
<!-- for some reason puts the comment and html on same line -->
<!-- prettier-ignore -->
```svelte
<div contenteditable="true" bind:innerHTML={html} />
```
`<details>` elements support binding to the `open` property.
```svelte
<details bind:open={isOpen}>
<summary>Details</summary>
<p>Something small enough to escape casual notice.</p>
</details>
```
## Media element bindings
Media elements (`<audio>` and `<video>`) have their own set of bindings — seven _readonly_ ones...
- `duration` (readonly) — the total duration of the video, in seconds
- `buffered` (readonly) — an array of `{start, end}` objects
- `played` (readonly) — ditto
- `seekable` (readonly) — ditto
- `seeking` (readonly) — boolean
- `ended` (readonly) — boolean
- `readyState` (readonly) — number between (and including) 0 and 4
...and five _two-way_ bindings:
- `currentTime` — the current playback time in the video, in seconds
- `playbackRate` — how fast or slow to play the video, where 1 is 'normal'
- `paused` — this one should be self-explanatory
- `volume` — a value between 0 and 1
- `muted` — a boolean value indicating whether the player is muted
Videos additionally have readonly `videoWidth` and `videoHeight` bindings.
```svelte
<video
src={clip}
bind:duration
bind:buffered
bind:played
bind:seekable
bind:seeking
bind:ended
bind:readyState
bind:currentTime
bind:playbackRate
bind:paused
bind:volume
bind:muted
bind:videoWidth
bind:videoHeight
/>
```
## Image element bindings
Image elements (`<img>`) have two readonly bindings:
- `naturalWidth` (readonly) — the original width of the image, available after the image has loaded
- `naturalHeight` (readonly) — the original height of the image, available after the image has loaded
```svelte
<img
bind:naturalWidth
bind:naturalHeight
></img>
```
## Block-level element bindings
Block-level elements have 4 read-only bindings, measured using a technique similar to [this one](http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/):
- `clientWidth`
- `clientHeight`
- `offsetWidth`
- `offsetHeight`
```svelte
<div bind:offsetWidth={width} bind:offsetHeight={height}>
<Chart {width} {height} />
</div>
```
## bind:group
```svelte
<!--- copy: false --->
bind:group={variable}
```
Inputs that work together can use `bind:group`.
```svelte
<script>
let tortilla = 'Plain';
/** @type {Array<string>} */
let fillings = [];
</script>
<!-- grouped radio inputs are mutually exclusive -->
<input type="radio" bind:group={tortilla} value="Plain" />
<input type="radio" bind:group={tortilla} value="Whole wheat" />
<input type="radio" bind:group={tortilla} value="Spinach" />
<!-- grouped checkbox inputs populate an array -->
<input type="checkbox" bind:group={fillings} value="Rice" />
<input type="checkbox" bind:group={fillings} value="Beans" />
<input type="checkbox" bind:group={fillings} value="Cheese" />
<input type="checkbox" bind:group={fillings} value="Guac (extra)" />
```
> `bind:group` only works if the inputs are in the same Svelte component.
## bind:this
```svelte
<!--- copy: false --->
bind:this={dom_node}
```
To get a reference to a DOM node, use `bind:this`.
```svelte
<script>
import { onMount } from 'svelte';
/** @type {HTMLCanvasElement} */
let canvasElement;
onMount(() => {
const ctx = canvasElement.getContext('2d');
drawStuff(ctx);
});
</script>
<canvas bind:this={canvasElement} />
```
## class:_name_
```svelte
<!--- copy: false --->
class:name={value}
```
```svelte
<!--- copy: false --->
class:name
```
A `class:` directive provides a shorter way of toggling a class on an element.
```svelte
<!-- These are equivalent -->
<div class={isActive ? 'active' : ''}>...</div>
<div class:active={isActive}>...</div>
<!-- Shorthand, for when name and value match -->
<div class:active>...</div>
<!-- Multiple class toggles can be included -->
<div class:active class:inactive={!active} class:isAdmin>...</div>
```
## style:_property_
```svelte
style:property={value}
```
```svelte
style:property="value"
```
```svelte
style:property
```
The `style:` directive provides a shorthand for setting multiple styles on an element.
```svelte
<!-- These are equivalent -->
<div style:color="red">...</div>
<div style="color: red;">...</div>
<!-- Variables can be used -->
<div style:color={myColor}>...</div>
<!-- Shorthand, for when property and variable name match -->
<div style:color>...</div>
<!-- Multiple styles can be included -->
<div style:color style:width="12rem" style:background-color={darkMode ? 'black' : 'white'}>...</div>
<!-- Styles can be marked as important -->
<div style:color|important="red">...</div>
```
When `style:` directives are combined with `style` attributes, the directives will take precedence:
```svelte
<div style="color: blue;" style:color="red">This will be red</div>
```
## use:_action_
```svelte
<!--- copy: false --->
use:action
```
```svelte
<!--- copy: false --->
use:action={parameters}
```
```ts
/// copy: false
// @noErrors
action = (node: HTMLElement, parameters: any) => {
update?: (parameters: any) => void,
destroy?: () => void
}
```
Actions are functions that are called when an element is created. They can return an object with a `destroy` method that is called after the element is unmounted:
```svelte
<script>
/** @type {import('svelte/action').Action} */
function foo(node) {
// the node has been mounted in the DOM
return {
destroy() {
// the node has been removed from the DOM
}
};
}
</script>
<div use:foo />
```
An action can have a parameter. If the returned value has an `update` method, it will be called whenever that parameter changes, immediately after Svelte has applied updates to the markup.
> Don't worry about the fact that we're redeclaring the `foo` function for every component instance — Svelte will hoist any functions that don't depend on local state out of the component definition.
```svelte
<script>
export let bar;
/** @type {import('svelte/action').Action} */
function foo(node, bar) {
// the node has been mounted in the DOM
return {
update(bar) {
// the value of `bar` has changed
},
destroy() {
// the node has been removed from the DOM
}
};
}
</script>
<div use:foo={bar} />
```
Read more in the [`svelte/action`](/docs/svelte-action) page.
## transition:_fn_
```svelte
<!--- copy: false --->
transition:fn
```
```svelte
<!--- copy: false --->
transition:fn={params}
```
```svelte
<!--- copy: false --->
transition:fn|global
```
```svelte
<!--- copy: false --->
transition:fn|global={params}
```
```svelte
<!--- copy: false --->
transition:fn|local
```
```svelte
<!--- copy: false --->
transition:fn|local={params}
```
```js
/// copy: false
// @noErrors
transition = (node: HTMLElement, params: any, options: { direction: 'in' | 'out' | 'both' }) => {
delay?: number,
duration?: number,
easing?: (t: number) => number,
css?: (t: number, u: number) => string,
tick?: (t: number, u: number) => void
}
```
A transition is triggered by an element entering or leaving the DOM as a result of a state change.
When a block is transitioning out, all elements inside the block, including those that do not have their own transitions, are kept in the DOM until every transition in the block has been completed.
The `transition:` directive indicates a _bidirectional_ transition, which means it can be smoothly reversed while the transition is in progress.
```svelte
{#if visible}
<div transition:fade>fades in and out</div>
{/if}
```
Transitions are local by default (in Svelte 3, they were global by default). Local transitions only play when the block they belong to is created or destroyed, _not_ when parent blocks are created or destroyed.
```svelte
{#if x}
{#if y}
<!-- Svelte 3: <p transition:fade|local> -->
<p transition:fade>fades in and out only when y changes</p>
<!-- Svelte 3: <p transition:fade> -->
<p transition:fade|global>fades in and out when x or y change</p>
{/if}
{/if}
```
> By default intro transitions will not play on first render. You can modify this behaviour by setting `intro: true` when you [create a component](/docs/client-side-component-api) and marking the transition as `global`.
## Transition parameters
Like actions, transitions can have parameters.
(The double `{{curlies}}` aren't a special syntax; this is an object literal inside an expression tag.)
```svelte
{#if visible}
<div transition:fade={{ duration: 2000 }}>fades in and out over two seconds</div>
{/if}
```
## Custom transition functions
Transitions can use custom functions. If the returned object has a `css` function, Svelte will create a CSS animation that plays on the element.
The `t` argument passed to `css` is a value between `0` and `1` after the `easing` function has been applied. _In_ transitions run from `0` to `1`, _out_ transitions run from `1` to `0` in other words, `1` is the element's natural state, as though no transition had been applied. The `u` argument is equal to `1 - t`.
The function is called repeatedly _before_ the transition begins, with different `t` and `u` arguments.
```svelte
<script>
import { elasticOut } from 'svelte/easing';
/** @type {boolean} */
export let visible;
/**
* @param {HTMLElement} node
* @param {{ delay?: number, duration?: number, easing?: (t: number) => number }} params
*/
function whoosh(node, params) {
const existingTransform = getComputedStyle(node).transform.replace('none', '');
return {
delay: params.delay || 0,
duration: params.duration || 400,
easing: params.easing || elasticOut,
css: (t, u) => `transform: ${existingTransform} scale(${t})`
};
}
</script>
{#if visible}
<div in:whoosh>whooshes in</div>
{/if}
```
A custom transition function can also return a `tick` function, which is called _during_ the transition with the same `t` and `u` arguments.
> If it's possible to use `css` instead of `tick`, do so — CSS animations can run off the main thread, preventing jank on slower devices.
```svelte
<!--- file: App.svelte --->
<script>
export let visible = false;
/**
* @param {HTMLElement} node
* @param {{ speed?: number }} params
*/
function typewriter(node, { speed = 1 }) {
const valid = node.childNodes.length === 1 && node.childNodes[0].nodeType === Node.TEXT_NODE;
if (!valid) {
throw new Error(`This transition only works on elements with a single text node child`);
}
const text = node.textContent;
const duration = text.length / (speed * 0.01);
return {
duration,
tick: (t) => {
const i = ~~(text.length * t);
node.textContent = text.slice(0, i);
}
};
}
</script>
{#if visible}
<p in:typewriter={{ speed: 1 }}>The quick brown fox jumps over the lazy dog</p>
{/if}
```
If a transition returns a function instead of a transition object, the function will be called in the next microtask. This allows multiple transitions to coordinate, making [crossfade effects](https://learn.svelte.dev/tutorial/deferred-transitions) possible.
Transition functions also receive a third argument, `options`, which contains information about the transition.
Available values in the `options` object are:
- `direction` - one of `in`, `out`, or `both` depending on the type of transition
## Transition events
An element with transitions will dispatch the following events in addition to any standard DOM events:
- `introstart`
- `introend`
- `outrostart`
- `outroend`
```svelte
{#if visible}
<p
transition:fly={{ y: 200, duration: 2000 }}
on:introstart={() => (status = 'intro started')}
on:outrostart={() => (status = 'outro started')}
on:introend={() => (status = 'intro ended')}
on:outroend={() => (status = 'outro ended')}
>
Flies in and out
</p>
{/if}
```
## in:_fn_/out:_fn_
```svelte
<!--- copy: false --->
in:fn
```
```svelte
<!--- copy: false --->
in:fn={params}
```
```svelte
<!--- copy: false --->
in:fn|global
```
```svelte
<!--- copy: false --->
in:fn|global={params}
```
```svelte
<!--- copy: false --->
in:fn|local
```
```svelte
<!--- copy: false --->
in:fn|local={params}
```
```svelte
<!--- copy: false --->
out:fn
```
```svelte
<!--- copy: false --->
out:fn={params}
```
```svelte
<!--- copy: false --->
out:fn|global
```
```svelte
<!--- copy: false --->
out:fn|global={params}
```
```svelte
<!--- copy: false --->
out:fn|local
```
```svelte
<!--- copy: false --->
out:fn|local={params}
```
Similar to `transition:`, but only applies to elements entering (`in:`) or leaving (`out:`) the DOM.
Unlike with `transition:`, transitions applied with `in:` and `out:` are not bidirectional — an in transition will continue to 'play' alongside the out transition, rather than reversing, if the block is outroed while the transition is in progress. If an out transition is aborted, transitions will restart from scratch.
```svelte
{#if visible}
<div in:fly out:fade>flies in, fades out</div>
{/if}
```
## animate:_fn_
```svelte
<!--- copy: false --->
animate:name
```
```svelte
<!--- copy: false --->
animate:name={params}
```
```js
/// copy: false
// @noErrors
animation = (node: HTMLElement, { from: DOMRect, to: DOMRect } , params: any) => {
delay?: number,
duration?: number,
easing?: (t: number) => number,
css?: (t: number, u: number) => string,
tick?: (t: number, u: number) => void
}
```
```ts
/// copy: false
// @noErrors
DOMRect {
bottom: number,
height: number,
left: number,
right: number,
top: number,
width: number,
x: number,
y: number
}
```
An animation is triggered when the contents of a [keyed each block](/docs/logic-blocks#each) are re-ordered. Animations do not run when an element is added or removed, only when the index of an existing data item within the each block changes. Animate directives must be on an element that is an _immediate_ child of a keyed each block.
Animations can be used with Svelte's [built-in animation functions](/docs/svelte-animate) or [custom animation functions](/docs/element-directives#custom-animation-functions).
```svelte
<!-- When `list` is reordered the animation will run-->
{#each list as item, index (item)}
<li animate:flip>{item}</li>
{/each}
```
## Animation Parameters
As with actions and transitions, animations can have parameters.
(The double `{{curlies}}` aren't a special syntax; this is an object literal inside an expression tag.)
```svelte
{#each list as item, index (item)}
<li animate:flip={{ delay: 500 }}>{item}</li>
{/each}
```
## Custom animation functions
Animations can use custom functions that provide the `node`, an `animation` object and any `parameters` as arguments. The `animation` parameter is an object containing `from` and `to` properties each containing a [DOMRect](https://developer.mozilla.org/en-US/docs/Web/API/DOMRect#Properties) describing the geometry of the element in its `start` and `end` positions. The `from` property is the DOMRect of the element in its starting position, and the `to` property is the DOMRect of the element in its final position after the list has been reordered and the DOM updated.
If the returned object has a `css` method, Svelte will create a CSS animation that plays on the element.
The `t` argument passed to `css` is a value that goes from `0` and `1` after the `easing` function has been applied. The `u` argument is equal to `1 - t`.
The function is called repeatedly _before_ the animation begins, with different `t` and `u` arguments.
<!-- TODO: Types -->
```svelte
<script>
import { cubicOut } from 'svelte/easing';
/**
* @param {HTMLElement} node
* @param {{ from: DOMRect; to: DOMRect }} states
* @param {any} params
*/
function whizz(node, { from, to }, params) {
const dx = from.left - to.left;
const dy = from.top - to.top;
const d = Math.sqrt(dx * dx + dy * dy);
return {
delay: 0,
duration: Math.sqrt(d) * 120,
easing: cubicOut,
css: (t, u) => `transform: translate(${u * dx}px, ${u * dy}px) rotate(${t * 360}deg);`
};
}
</script>
{#each list as item, index (item)}
<div animate:whizz>{item}</div>
{/each}
```
A custom animation function can also return a `tick` function, which is called _during_ the animation with the same `t` and `u` arguments.
> If it's possible to use `css` instead of `tick`, do so — CSS animations can run off the main thread, preventing jank on slower devices.
```svelte
<script>
import { cubicOut } from 'svelte/easing';
/**
* @param {HTMLElement} node
* @param {{ from: DOMRect; to: DOMRect }} states
* @param {any} params
*/
function whizz(node, { from, to }, params) {
const dx = from.left - to.left;
const dy = from.top - to.top;
const d = Math.sqrt(dx * dx + dy * dy);
return {
delay: 0,
duration: Math.sqrt(d) * 120,
easing: cubicOut,
tick: (t, u) => Object.assign(node.style, { color: t > 0.5 ? 'Pink' : 'Blue' })
};
}
</script>
{#each list as item, index (item)}
<div animate:whizz>{item}</div>
{/each}
```

@ -0,0 +1,214 @@
---
title: Styles & Classes
---
- style scoping
- `:global`
- `style:`
- `class:`
- `--css` props
Styling is a fundamental part of UI components. Svelte helps you style your components with ease, providing useful features out of the box.
## Scoped by default
By default CSS inside a `<style>` block will be scoped to that component.
This works by adding a class to affected elements, which is based on a hash of the component styles (e.g. `svelte-123xyz`).
```svelte
<style>
p {
/* this will only affect <p> elements in this component */
color: burlywood;
}
</style>
```
## :global
To apply styles to a selector globally, use the `:global(...)` modifier.
```svelte
<style>
:global(body) {
/* this will apply to <body> */
margin: 0;
}
div :global(strong) {
/* this will apply to all <strong> elements, in any
component, that are inside <div> elements belonging
to this component */
color: goldenrod;
}
p:global(.red) {
/* this will apply to all <p> elements belonging to this
component with a class of red, even if class="red" does
not initially appear in the markup, and is instead
added at runtime. This is useful when the class
of the element is dynamically applied, for instance
when updating the element's classList property directly. */
}
</style>
```
If you want to make @keyframes that are accessible globally, you need to prepend your keyframe names with `-global-`.
The `-global-` part will be removed when compiled, and the keyframe will then be referenced using just `my-animation-name` elsewhere in your code.
```svelte
<style>
@keyframes -global-my-animation-name {
/* code goes here */
}
</style>
```
## Nested style tags
There should only be 1 top-level `<style>` tag per component.
However, it is possible to have a `<style>` tag nested inside other elements or logic blocks.
In that case, the `<style>` tag will be inserted as-is into the DOM; no scoping or processing will be done on the `<style>` tag.
```svelte
<div>
<style>
/* this style tag will be inserted as-is */
div {
/* this will apply to all `<div>` elements in the DOM */
color: red;
}
</style>
</div>
```
## class:_name_
```svelte
<!--- copy: false --->
class:name={value}
```
```svelte
<!--- copy: false --->
class:name
```
A `class:` directive provides a shorter way of toggling a class on an element.
```svelte
<!-- These are equivalent -->
<div class={isActive ? 'active' : ''}>...</div>
<div class:active={isActive}>...</div>
<!-- Shorthand, for when name and value match -->
<div class:active>...</div>
<!-- Multiple class toggles can be included -->
<div class:active class:inactive={!active} class:isAdmin>...</div>
```
## style:_property_
```svelte
<!--- copy: false --->
style:property={value}
```
```svelte
<!--- copy: false --->
style:property="value"
```
```svelte
<!--- copy: false --->
style:property
```
The `style:` directive provides a shorthand for setting multiple styles on an element.
```svelte
<!-- These are equivalent -->
<div style:color="red">...</div>
<div style="color: red;">...</div>
<!-- Variables can be used -->
<div style:color={myColor}>...</div>
<!-- Shorthand, for when property and variable name match -->
<div style:color>...</div>
<!-- Multiple styles can be included -->
<div style:color style:width="12rem" style:background-color={darkMode ? 'black' : 'white'}>...</div>
<!-- Styles can be marked as important -->
<div style:color|important="red">...</div>
```
When `style:` directives are combined with `style` attributes, the directives will take precedence:
```svelte
<div style="color: blue;" style:color="red">This will be red</div>
```
## --style-props
```svelte
<!--- copy: false --->
--style-props="anycssvalue"
```
You can also pass styles as props to components for the purposes of theming, using CSS custom properties.
Svelte's implementation is essentially syntactic sugar for adding a wrapper element. This example:
```svelte
<Slider bind:value min={0} --rail-color="black" --track-color="rgb(0, 0, 255)" />
```
Desugars to this:
```svelte
<div style="display: contents; --rail-color: black; --track-color: rgb(0, 0, 255)">
<Slider bind:value min={0} max={100} />
</div>
```
For SVG namespace, the example above desugars into using `<g>` instead:
```svelte
<g style="--rail-color: black; --track-color: rgb(0, 0, 255)">
<Slider bind:value min={0} max={100} />
</g>
```
> Since this is an extra `<div>` (or `<g>`), beware that your CSS structure might accidentally target this. Be mindful of this added wrapper element when using this feature.
Svelte's CSS Variables support allows for easily themeable components:
```svelte
<style>
.potato-slider-rail {
background-color: var(--rail-color, var(--theme-color, 'purple'));
}
</style>
```
So you can set a high-level theme color:
```css
/* global.css */
html {
--theme-color: black;
}
```
Or override it at the consumer level:
```svelte
<Slider --rail-color="goldenrod" />
```

@ -1,129 +0,0 @@
---
title: Component directives
---
## on:_eventname_
```svelte
<!--- copy: false --->
on:eventname={handler}
```
Components can emit events using [`createEventDispatcher`](/docs/svelte#createeventdispatcher) or by forwarding DOM events.
```svelte
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
</script>
<!-- programmatic dispatching -->
<button on:click={() => dispatch('hello')}> one </button>
<!-- declarative event forwarding -->
<button on:click> two </button>
```
Listening for component events looks the same as listening for DOM events:
```svelte
<SomeComponent on:whatever={handler} />
```
As with DOM events, if the `on:` directive is used without a value, the event will be forwarded, meaning that a consumer can listen for it.
```svelte
<SomeComponent on:whatever />
```
## --style-props
```svelte
<!--- copy: false --->
--style-props="anycssvalue"
```
You can also pass styles as props to components for the purposes of theming, using CSS custom properties.
Svelte's implementation is essentially syntactic sugar for adding a wrapper element. This example:
```svelte
<Slider bind:value min={0} --rail-color="black" --track-color="rgb(0, 0, 255)" />
```
Desugars to this:
```svelte
<div style="display: contents; --rail-color: black; --track-color: rgb(0, 0, 255)">
<Slider bind:value min={0} max={100} />
</div>
```
**Note**: Since this is an extra `<div>`, beware that your CSS structure might accidentally target this. Be mindful of this added wrapper element when using this feature.
For SVG namespace, the example above desugars into using `<g>` instead:
```svelte
<g style="--rail-color: black; --track-color: rgb(0, 0, 255)">
<Slider bind:value min={0} max={100} />
</g>
```
**Note**: Since this is an extra `<g>`, beware that your CSS structure might accidentally target this. Be mindful of this added wrapper element when using this feature.
Svelte's CSS Variables support allows for easily themeable components:
```svelte
<style>
.potato-slider-rail {
background-color: var(--rail-color, var(--theme-color, 'purple'));
}
</style>
```
So you can set a high-level theme color:
```css
/* global.css */
html {
--theme-color: black;
}
```
Or override it at the consumer level:
```svelte
<Slider --rail-color="goldenrod" />
```
## bind:_property_
```svelte
bind:property={variable}
```
You can bind to component props using the same syntax as for elements.
```svelte
<Keypad bind:value={pin} />
```
While Svelte props are reactive without binding, that reactivity only flows downward into the component by default. Using `bind:property` allows changes to the property from within the component to flow back up out of the component.
## bind:this
```svelte
<!--- copy: false --->
bind:this={component_instance}
```
Components also support `bind:this`, allowing you to interact with component instances programmatically.
```svelte
<ShoppingCart bind:this={cart} />
<button on:click={() => cart.empty()}> Empty shopping cart </button>
```
> Note that we can't do `{cart.empty}` since `cart` is `undefined` when the button is first rendered and throws an error.

@ -0,0 +1,432 @@
---
title: Transitions & Animations
---
- how to use (template syntax)
- when to use
- global vs local
- easing & motion
- mention imports
- key block
Svelte provides different techniques and syntax for incorporating motion into your Svelte projects.
## transition:_fn_
```svelte
<!--- copy: false --->
transition:fn
```
```svelte
<!--- copy: false --->
transition:fn={params}
```
```svelte
<!--- copy: false --->
transition:fn|global
```
```svelte
<!--- copy: false --->
transition:fn|global={params}
```
```svelte
<!--- copy: false --->
transition:fn|local
```
```svelte
<!--- copy: false --->
transition:fn|local={params}
```
```js
/// copy: false
// @noErrors
transition = (node: HTMLElement, params: any, options: { direction: 'in' | 'out' | 'both' }) => {
delay?: number,
duration?: number,
easing?: (t: number) => number,
css?: (t: number, u: number) => string,
tick?: (t: number, u: number) => void
}
```
A transition is triggered by an element entering or leaving the DOM as a result of a state change.
When a block is transitioning out, all elements inside the block, including those that do not have their own transitions, are kept in the DOM until every transition in the block has been completed.
The `transition:` directive indicates a _bidirectional_ transition, which means it can be smoothly reversed while the transition is in progress.
```svelte
{#if visible}
<div transition:fade>fades in and out</div>
{/if}
```
Transitions are local by default. Local transitions only play when the block they belong to is created or destroyed, _not_ when parent blocks are created or destroyed.
```svelte
{#if x}
{#if y}
<p transition:fade>fades in and out only when y changes</p>
<p transition:fade|global>fades in and out when x or y change</p>
{/if}
{/if}
```
> By default intro transitions will not play on first render. You can modify this behaviour by setting `intro: true` when you [create a component](/docs/runtime/imperative-component-api) and marking the transition as `global`.
## Transition parameters
Transitions can have parameters.
(The double `{{curlies}}` aren't a special syntax; this is an object literal inside an expression tag.)
```svelte
{#if visible}
<div transition:fade={{ duration: 2000 }}>fades in and out over two seconds</div>
{/if}
```
## Custom transition functions
Transitions can use custom functions. If the returned object has a `css` function, Svelte will create a CSS animation that plays on the element.
The `t` argument passed to `css` is a value between `0` and `1` after the `easing` function has been applied. _In_ transitions run from `0` to `1`, _out_ transitions run from `1` to `0` in other words, `1` is the element's natural state, as though no transition had been applied. The `u` argument is equal to `1 - t`.
The function is called repeatedly _before_ the transition begins, with different `t` and `u` arguments.
```svelte
<script>
import { elasticOut } from 'svelte/easing';
/** @type {boolean} */
export let visible;
/**
* @param {HTMLElement} node
* @param {{ delay?: number, duration?: number, easing?: (t: number) => number }} params
*/
function whoosh(node, params) {
const existingTransform = getComputedStyle(node).transform.replace('none', '');
return {
delay: params.delay || 0,
duration: params.duration || 400,
easing: params.easing || elasticOut,
css: (t, u) => `transform: ${existingTransform} scale(${t})`
};
}
</script>
{#if visible}
<div in:whoosh>whooshes in</div>
{/if}
```
A custom transition function can also return a `tick` function, which is called _during_ the transition with the same `t` and `u` arguments.
> If it's possible to use `css` instead of `tick`, do so — CSS animations can run off the main thread, preventing jank on slower devices.
```svelte
<!--- file: App.svelte --->
<script>
export let visible = false;
/**
* @param {HTMLElement} node
* @param {{ speed?: number }} params
*/
function typewriter(node, { speed = 1 }) {
const valid = node.childNodes.length === 1 && node.childNodes[0].nodeType === Node.TEXT_NODE;
if (!valid) {
throw new Error(`This transition only works on elements with a single text node child`);
}
const text = node.textContent;
const duration = text.length / (speed * 0.01);
return {
duration,
tick: (t) => {
const i = ~~(text.length * t);
node.textContent = text.slice(0, i);
}
};
}
</script>
{#if visible}
<p in:typewriter={{ speed: 1 }}>The quick brown fox jumps over the lazy dog</p>
{/if}
```
If a transition returns a function instead of a transition object, the function will be called in the next microtask. This allows multiple transitions to coordinate, making [crossfade effects](/tutorial/deferred-transitions) possible.
Transition functions also receive a third argument, `options`, which contains information about the transition.
Available values in the `options` object are:
- `direction` - one of `in`, `out`, or `both` depending on the type of transition
## Transition events
An element with transitions will dispatch the following events in addition to any standard DOM events:
- `introstart`
- `introend`
- `outrostart`
- `outroend`
```svelte
{#if visible}
<p
transition:fly={{ y: 200, duration: 2000 }}
on:introstart={() => (status = 'intro started')}
on:outrostart={() => (status = 'outro started')}
on:introend={() => (status = 'intro ended')}
on:outroend={() => (status = 'outro ended')}
>
Flies in and out
</p>
{/if}
```
## in:_fn_/out:_fn_
```svelte
<!--- copy: false --->
in:fn
```
```svelte
<!--- copy: false --->
in:fn={params}
```
```svelte
<!--- copy: false --->
in:fn|global
```
```svelte
<!--- copy: false --->
in:fn|global={params}
```
```svelte
<!--- copy: false --->
in:fn|local
```
```svelte
<!--- copy: false --->
in:fn|local={params}
```
```svelte
<!--- copy: false --->
out:fn
```
```svelte
<!--- copy: false --->
out:fn={params}
```
```svelte
<!--- copy: false --->
out:fn|global
```
```svelte
<!--- copy: false --->
out:fn|global={params}
```
```svelte
<!--- copy: false --->
out:fn|local
```
```svelte
<!--- copy: false --->
out:fn|local={params}
```
Similar to `transition:`, but only applies to elements entering (`in:`) or leaving (`out:`) the DOM.
Unlike with `transition:`, transitions applied with `in:` and `out:` are not bidirectional — an in transition will continue to 'play' alongside the out transition, rather than reversing, if the block is outroed while the transition is in progress. If an out transition is aborted, transitions will restart from scratch.
```svelte
{#if visible}
<div in:fly out:fade>flies in, fades out</div>
{/if}
```
## animate:_fn_
```svelte
<!--- copy: false --->
animate:name
```
```svelte
<!--- copy: false --->
animate:name={params}
```
```js
/// copy: false
// @noErrors
animation = (node: HTMLElement, { from: DOMRect, to: DOMRect } , params: any) => {
delay?: number,
duration?: number,
easing?: (t: number) => number,
css?: (t: number, u: number) => string,
tick?: (t: number, u: number) => void
}
```
```ts
/// copy: false
// @noErrors
DOMRect {
bottom: number,
height: number,
left: number,
right: number,
top: number,
width: number,
x: number,
y: number
}
```
An animation is triggered when the contents of a [keyed each block](control-flow#each) are re-ordered. Animations do not run when an element is added or removed, only when the index of an existing data item within the each block changes. Animate directives must be on an element that is an _immediate_ child of a keyed each block.
Animations can be used with Svelte's [built-in animation functions](/docs/svelte/reference/svelte-animate) or [custom animation functions](#custom-animation-functions).
```svelte
<!-- When `list` is reordered the animation will run-->
{#each list as item, index (item)}
<li animate:flip>{item}</li>
{/each}
```
## Animation Parameters
As with actions and transitions, animations can have parameters.
(The double `{{curlies}}` aren't a special syntax; this is an object literal inside an expression tag.)
```svelte
{#each list as item, index (item)}
<li animate:flip={{ delay: 500 }}>{item}</li>
{/each}
```
## Custom animation functions
Animations can use custom functions that provide the `node`, an `animation` object and any `parameters` as arguments. The `animation` parameter is an object containing `from` and `to` properties each containing a [DOMRect](https://developer.mozilla.org/en-US/docs/Web/API/DOMRect#Properties) describing the geometry of the element in its `start` and `end` positions. The `from` property is the DOMRect of the element in its starting position, and the `to` property is the DOMRect of the element in its final position after the list has been reordered and the DOM updated.
If the returned object has a `css` method, Svelte will create a CSS animation that plays on the element.
The `t` argument passed to `css` is a value that goes from `0` and `1` after the `easing` function has been applied. The `u` argument is equal to `1 - t`.
The function is called repeatedly _before_ the animation begins, with different `t` and `u` arguments.
<!-- TODO: Types -->
```svelte
<script>
import { cubicOut } from 'svelte/easing';
/**
* @param {HTMLElement} node
* @param {{ from: DOMRect; to: DOMRect }} states
* @param {any} params
*/
function whizz(node, { from, to }, params) {
const dx = from.left - to.left;
const dy = from.top - to.top;
const d = Math.sqrt(dx * dx + dy * dy);
return {
delay: 0,
duration: Math.sqrt(d) * 120,
easing: cubicOut,
css: (t, u) => `transform: translate(${u * dx}px, ${u * dy}px) rotate(${t * 360}deg);`
};
}
</script>
{#each list as item, index (item)}
<div animate:whizz>{item}</div>
{/each}
```
A custom animation function can also return a `tick` function, which is called _during_ the animation with the same `t` and `u` arguments.
> If it's possible to use `css` instead of `tick`, do so — CSS animations can run off the main thread, preventing jank on slower devices.
```svelte
<script>
import { cubicOut } from 'svelte/easing';
/**
* @param {HTMLElement} node
* @param {{ from: DOMRect; to: DOMRect }} states
* @param {any} params
*/
function whizz(node, { from, to }, params) {
const dx = from.left - to.left;
const dy = from.top - to.top;
const d = Math.sqrt(dx * dx + dy * dy);
return {
delay: 0,
duration: Math.sqrt(d) * 120,
easing: cubicOut,
tick: (t, u) => Object.assign(node.style, { color: t > 0.5 ? 'Pink' : 'Blue' })
};
}
</script>
{#each list as item, index (item)}
<div animate:whizz>{item}</div>
{/each}
```
## {#key ...}
```svelte
<!--- copy: false --->
{#key expression}...{/key}
```
Key blocks destroy and recreate their contents when the value of an expression changes.
This is useful if you want an element to play its transition whenever a value changes.
```svelte
{#key value}
<div transition:fade>{value}</div>
{/key}
```
When used around components, this will cause them to be reinstantiated and reinitialised.
```svelte
{#key value}
<Component />
{/key}
```

@ -1,10 +1,35 @@
---
title: svelte/action
title: Actions
---
- template syntax
- how to write
- typings
- adjust so that `$effect` is used instead of update/destroy?
```svelte
<!--- copy: false --->
use:action
```
```svelte
<!--- copy: false --->
use:action={parameters}
```
```ts
/// copy: false
// @noErrors
action = (node: HTMLElement, parameters: any) => {
update?: (parameters: any) => void,
destroy?: () => void
}
```
Actions are functions that are called when an element is created. They can return an object with a `destroy` method that is called after the element is unmounted:
```svelte
<!--- file: App.svelte --->
<script>
/** @type {import('svelte/action').Action} */
function foo(node) {
@ -26,6 +51,7 @@ An action can have a parameter. If the returned value has an `update` method, it
> Don't worry that we're redeclaring the `foo` function for every component instance — Svelte will hoist any functions that don't depend on local state out of the component definition.
```svelte
<!--- file: App.svelte --->
<script>
/** @type {string} */
export let bar;
@ -54,6 +80,7 @@ An action can have a parameter. If the returned value has an `update` method, it
Sometimes actions emit custom events and apply custom attributes to the element they are applied to. To support this, actions typed with `Action` or `ActionReturn` type can have a last parameter, `Attributes`:
```svelte
<!--- file: App.svelte --->
<script>
/**
* @type {import('svelte/action').Action<HTMLDivElement, { prop: any }, { 'on:emit': (e: CustomEvent<string>) => void }>}
@ -72,9 +99,5 @@ Sometimes actions emit custom events and apply custom attributes to the element
}
</script>
<div use:foo={{ prop: 'someValue' }} on:emit={handleEmit} />
<div use:foo={{ prop: 'someValue' }} onemit={handleEmit} />
```
## Types
> TYPES: svelte/action

@ -0,0 +1,305 @@
---
title: Bindings
---
- how for dom elements
- list of all bindings
- how for components
Most of the time a clear separation between data flowing down and events going up is worthwhile and results in more robust apps. But in some cases - especially when interacting with form elements - it's more ergonomic to declare a two way binding. Svelte provides many element bindings out of the box, and also allows component bindings.
## bind:_property_ for elements
```svelte
<!--- copy: false --->
bind:property={variable}
```
Data ordinarily flows down, from parent to child. The `bind:` directive allows data to flow the other way, from child to parent. Most bindings are specific to particular elements.
The simplest bindings reflect the value of a property, such as `input.value`.
```svelte
<input bind:value={name} />
<textarea bind:value={text} />
<input type="checkbox" bind:checked={yes} />
```
If the name matches the value, you can use a shorthand.
```svelte
<input bind:value />
<!-- equivalent to
<input bind:value={value} />
-->
```
Numeric input values are coerced; even though `input.value` is a string as far as the DOM is concerned, Svelte will treat it as a number. If the input is empty or invalid (in the case of `type="number"`), the value is `undefined`.
```svelte
<input type="number" bind:value={num} />
<input type="range" bind:value={num} />
```
On `<input>` elements with `type="file"`, you can use `bind:files` to get the [`FileList` of selected files](https://developer.mozilla.org/en-US/docs/Web/API/FileList). It is readonly.
```svelte
<label for="avatar">Upload a picture:</label>
<input accept="image/png, image/jpeg" bind:files id="avatar" name="avatar" type="file" />
```
If you're using `bind:` directives together with `on:` directives, the order that they're defined in affects the value of the bound variable when the event handler is called.
```svelte
<script>
let value = 'Hello World';
</script>
<input
on:input={() => console.log('Old value:', value)}
bind:value
on:input={() => console.log('New value:', value)}
/>
```
Here we were binding to the value of a text input, which uses the `input` event. Bindings on other elements may use different events such as `change`.
## Binding `<select>` value
A `<select>` value binding corresponds to the `value` property on the selected `<option>`, which can be any value (not just strings, as is normally the case in the DOM).
```svelte
<select bind:value={selected}>
<option value={a}>a</option>
<option value={b}>b</option>
<option value={c}>c</option>
</select>
```
A `<select multiple>` element behaves similarly to a checkbox group. The bound variable is an array with an entry corresponding to the `value` property of each selected `<option>`.
```svelte
<select multiple bind:value={fillings}>
<option value="Rice">Rice</option>
<option value="Beans">Beans</option>
<option value="Cheese">Cheese</option>
<option value="Guac (extra)">Guac (extra)</option>
</select>
```
When the value of an `<option>` matches its text content, the attribute can be omitted.
```svelte
<select multiple bind:value={fillings}>
<option>Rice</option>
<option>Beans</option>
<option>Cheese</option>
<option>Guac (extra)</option>
</select>
```
Elements with the `contenteditable` attribute support the following bindings:
- [`innerHTML`](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML)
- [`innerText`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText)
- [`textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
There are slight differences between each of these, read more about them [here](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent#Differences_from_innerText).
<!-- for some reason puts the comment and html on same line -->
<!-- prettier-ignore -->
```svelte
<div contenteditable="true" bind:innerHTML={html} />
```
`<details>` elements support binding to the `open` property.
```svelte
<details bind:open={isOpen}>
<summary>Details</summary>
<p>Something small enough to escape casual notice.</p>
</details>
```
## Media element bindings
Media elements (`<audio>` and `<video>`) have their own set of bindings — seven _readonly_ ones...
- `duration` (readonly) — the total duration of the video, in seconds
- `buffered` (readonly) — an array of `{start, end}` objects
- `played` (readonly) — ditto
- `seekable` (readonly) — ditto
- `seeking` (readonly) — boolean
- `ended` (readonly) — boolean
- `readyState` (readonly) — number between (and including) 0 and 4
...and five _two-way_ bindings:
- `currentTime` — the current playback time in the video, in seconds
- `playbackRate` — how fast or slow to play the video, where 1 is 'normal'
- `paused` — this one should be self-explanatory
- `volume` — a value between 0 and 1
- `muted` — a boolean value indicating whether the player is muted
Videos additionally have readonly `videoWidth` and `videoHeight` bindings.
```svelte
<video
src={clip}
bind:duration
bind:buffered
bind:played
bind:seekable
bind:seeking
bind:ended
bind:readyState
bind:currentTime
bind:playbackRate
bind:paused
bind:volume
bind:muted
bind:videoWidth
bind:videoHeight
/>
```
## Image element bindings
Image elements (`<img>`) have two readonly bindings:
- `naturalWidth` (readonly) — the original width of the image, available after the image has loaded
- `naturalHeight` (readonly) — the original height of the image, available after the image has loaded
```svelte
<img
bind:naturalWidth
bind:naturalHeight
></img>
```
## Block-level element bindings
Block-level elements have 4 read-only bindings, measured using a technique similar to [this one](http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/):
- `clientWidth`
- `clientHeight`
- `offsetWidth`
- `offsetHeight`
```svelte
<div bind:offsetWidth={width} bind:offsetHeight={height}>
<Chart {width} {height} />
</div>
```
## bind:group
```svelte
<!--- copy: false --->
bind:group={variable}
```
Inputs that work together can use `bind:group`.
```svelte
<script>
let tortilla = 'Plain';
/** @type {Array<string>} */
let fillings = [];
</script>
<!-- grouped radio inputs are mutually exclusive -->
<input type="radio" bind:group={tortilla} value="Plain" />
<input type="radio" bind:group={tortilla} value="Whole wheat" />
<input type="radio" bind:group={tortilla} value="Spinach" />
<!-- grouped checkbox inputs populate an array -->
<input type="checkbox" bind:group={fillings} value="Rice" />
<input type="checkbox" bind:group={fillings} value="Beans" />
<input type="checkbox" bind:group={fillings} value="Cheese" />
<input type="checkbox" bind:group={fillings} value="Guac (extra)" />
```
> `bind:group` only works if the inputs are in the same Svelte component.
## bind:this
```svelte
<!--- copy: false --->
bind:this={dom_node}
```
To get a reference to a DOM node, use `bind:this`.
```svelte
<script>
import { onMount } from 'svelte';
/** @type {HTMLCanvasElement} */
let canvasElement;
onMount(() => {
const ctx = canvasElement.getContext('2d');
drawStuff(ctx);
});
</script>
<canvas bind:this={canvasElement} />
```
Components also support `bind:this`, allowing you to interact with component instances programmatically.
```svelte
<!--- App.svelte --->
<ShoppingCart bind:this={cart} />
<button onclick={() => cart.empty()}> Empty shopping cart </button>
```
```svelte
<!--- ShoppingCart.svelte --->
<script>
// All instance exports are available on the instance object
export function empty() {
// ...
}
</script>
```
> Note that we can't do `{cart.empty}` since `cart` is `undefined` when the button is first rendered and throws an error.
## bind:_property_ for components
```svelte
bind:property={variable}
```
You can bind to component props using the same syntax as for elements.
```svelte
<Keypad bind:value={pin} />
```
While Svelte props are reactive without binding, that reactivity only flows downward into the component by default. Using `bind:property` allows changes to the property from within the component to flow back up out of the component.
To mark a property as bindable, use the `$bindable` rune:
```svelte
<script>
let { readonlyProperty, bindableProperty = $bindable() } = $props();
</script>
```
Declaring a property as bindable means it _can_ be used using `bind:`, not that it _must_ be used using `bind:`.
Bindable properties can have a fallback value:
```svelte
<script>
let { bindableProperty = $bindable('fallback value') } = $props();
</script>
```
This fallback value _only_ applies when the property is _not_ bound. When the property is bound and a fallback value is present, the parent is expected to provide a value other than `undefined`, else a runtime error is thrown. This prevents hard-to-reason-about situations where it's unclear which value should apply.

@ -2,149 +2,9 @@
title: Special elements
---
## `<slot>`
- [basically what we have in the docs today](https://svelte.dev/docs/special-elements)
```svelte
<slot><!-- optional fallback --></slot>
```
```svelte
<slot name="x"><!-- optional fallback --></slot>
```
```svelte
<slot prop={value} />
```
Components can have child content, in the same way that elements can.
The content is exposed in the child component using the `<slot>` element, which can contain fallback content that is rendered if no children are provided.
```svelte
<!-- Widget.svelte -->
<div>
<slot>
this fallback content will be rendered when no content is provided, like in the first example
</slot>
</div>
<!-- App.svelte -->
<Widget />
<!-- this component will render the default content -->
<Widget>
<p>this is some child content that will overwrite the default slot content</p>
</Widget>
```
Note: If you want to render regular `<slot>` element, You can use `<svelte:element this="slot" />`.
### `<slot name="`_name_`">`
Named slots allow consumers to target specific areas. They can also have fallback content.
```svelte
<!-- Widget.svelte -->
<div>
<slot name="header">No header was provided</slot>
<p>Some content between header and footer</p>
<slot name="footer" />
</div>
<!-- App.svelte -->
<Widget>
<h1 slot="header">Hello</h1>
<p slot="footer">Copyright (c) 2019 Svelte Industries</p>
</Widget>
```
Components can be placed in a named slot using the syntax `<Component slot="name" />`.
In order to place content in a slot without using a wrapper element, you can use the special element `<svelte:fragment>`.
```svelte
<!-- Widget.svelte -->
<div>
<slot name="header">No header was provided</slot>
<p>Some content between header and footer</p>
<slot name="footer" />
</div>
<!-- App.svelte -->
<Widget>
<HeaderComponent slot="header" />
<svelte:fragment slot="footer">
<p>All rights reserved.</p>
<p>Copyright (c) 2019 Svelte Industries</p>
</svelte:fragment>
</Widget>
```
### $$slots
`$$slots` is an object whose keys are the names of the slots passed into the component by the parent. If the parent does not pass in a slot with a particular name, that name will not be present in `$$slots`. This allows components to render a slot (and other elements, like wrappers for styling) only if the parent provides it.
Note that explicitly passing in an empty named slot will add that slot's name to `$$slots`. For example, if a parent passes `<div slot="title" />` to a child component, `$$slots.title` will be truthy within the child.
```svelte
<!-- Card.svelte -->
<div>
<slot name="title" />
{#if $$slots.description}
<!-- This <hr> and slot will render only if a slot named "description" is provided. -->
<hr />
<slot name="description" />
{/if}
</div>
<!-- App.svelte -->
<Card>
<h1 slot="title">Blog Post Title</h1>
<!-- No slot named "description" was provided so the optional slot will not be rendered. -->
</Card>
```
### `<slot key={`_value_`}>`
Slots can be rendered zero or more times and can pass values _back_ to the parent using props. The parent exposes the values to the slot template using the `let:` directive.
The usual shorthand rules apply — `let:item` is equivalent to `let:item={item}`, and `<slot {item}>` is equivalent to `<slot item={item}>`.
```svelte
<!-- FancyList.svelte -->
<ul>
{#each items as item}
<li class="fancy">
<slot prop={item} />
</li>
{/each}
</ul>
<!-- App.svelte -->
<FancyList {items} let:prop={thing}>
<div>{thing.text}</div>
</FancyList>
```
Named slots can also expose values. The `let:` directive goes on the element with the `slot` attribute.
```svelte
<!-- FancyList.svelte -->
<ul>
{#each items as item}
<li class="fancy">
<slot name="item" {item} />
</li>
{/each}
</ul>
<slot name="footer" />
<!-- App.svelte -->
<FancyList {items}>
<div slot="item" let:item>{item.text}</div>
<p slot="footer">Copyright (c) 2019 Svelte Industries</p>
</FancyList>
```
Some of Svelte's concepts need special elements. Those are prefixed with `svelte:` and listed here.
## `<svelte:self>`
@ -324,25 +184,3 @@ The `<svelte:options>` element provides a place to specify per-component compile
```svelte
<svelte:options customElement="my-custom-element" />
```
## `<svelte:fragment>`
The `<svelte:fragment>` element allows you to place content in a [named slot](/docs/special-elements#slot-slot-name-name) without wrapping it in a container DOM element. This keeps the flow layout of your document intact.
```svelte
<!-- Widget.svelte -->
<div>
<slot name="header">No header was provided</slot>
<p>Some content between header and footer</p>
<slot name="footer" />
</div>
<!-- App.svelte -->
<Widget>
<h1 slot="header">Hello</h1>
<svelte:fragment slot="footer">
<p>All rights reserved.</p>
<p>Copyright (c) 2019 Svelte Industries</p>
</svelte:fragment>
</Widget>
```

@ -0,0 +1,85 @@
---
title: Data fetching
---
Fetching data is a fundamental part of apps interacting with the outside world. Svelte is unopinionated with how you fetch your data. The simplest way would be using the built-in `fetch` method:
```svelte
<script>
let response = $state();
fetch('/api/data').then(async (r) => (response = r.json()));
</script>
```
While this works, it makes working with promises somewhat unergonomic. Svelte alleviates this problem using the `#await` block.
## {#await ...}
```svelte
<!--- copy: false --->
{#await expression}...{:then name}...{:catch name}...{/await}
```
```svelte
<!--- copy: false --->
{#await expression}...{:then name}...{/await}
```
```svelte
<!--- copy: false --->
{#await expression then name}...{/await}
```
```svelte
<!--- copy: false --->
{#await expression catch name}...{/await}
```
Await blocks allow you to branch on the three possible states of a Promise — pending, fulfilled or rejected.
In SSR mode, only the pending branch will be rendered on the server.
If the provided expression is not a Promise only the fulfilled branch will be rendered, including in SSR mode.
```svelte
{#await promise}
<!-- promise is pending -->
<p>waiting for the promise to resolve...</p>
{:then value}
<!-- promise was fulfilled or not a Promise -->
<p>The value is {value}</p>
{:catch error}
<!-- promise was rejected -->
<p>Something went wrong: {error.message}</p>
{/await}
```
The `catch` block can be omitted if you don't need to render anything when the promise rejects (or no error is possible).
```svelte
{#await promise}
<!-- promise is pending -->
<p>waiting for the promise to resolve...</p>
{:then value}
<!-- promise was fulfilled -->
<p>The value is {value}</p>
{/await}
```
If you don't care about the pending state, you can also omit the initial block.
```svelte
{#await promise then value}
<p>The value is {value}</p>
{/await}
```
Similarly, if you only want to show the error state, you can omit the `then` block.
```svelte
{#await promise catch error}
<p>The error is {error}</p>
{/await}
```
## SvelteKit loaders
Fetching inside your components is great for simple use cases, but it's prone to data loading waterfalls and makes code harder to work with because of the promise handling. SvelteKit solves this problem by providing a opinionated data loading story that is coupled to its router. Learn more about it [in the docs](/docs/kit).

@ -0,0 +1,3 @@
---
title: Template syntax
---

@ -1,3 +0,0 @@
{
"title": "Template Syntax"
}

@ -0,0 +1,234 @@
---
title: State
---
- `$state` (.frozen)
- `$derived` (.by)
- using classes
- getters/setters (what to do to keep reactivity "alive")
- universal reactivity
Svelte 5 uses _runes_, a powerful set of primitives for controlling reactivity inside your Svelte components and inside `.svelte.js` and `.svelte.ts` modules.
Runes are function-like symbols that provide instructions to the Svelte compiler. You don't need to import them from anywhere — when you use Svelte, they're part of the language. This page describes the runes that are concerned with managing state in your application.
## `$state`
The `$state` rune is the at the heart of the runes API. It is used to declare reactive state:
```svelte
<script>
let count = $state(0);
</script>
<button onclick={() => count++}>
clicks: {count}
</button>
```
Variables declared with `$state` are the variable _itself_, in other words there's no wrapper around the value that it contains. This is possible thanks to the compiler-nature of Svelte. As such, updating state is done through simple reassignment.
You can also use `$state` in class fields (whether public or private):
```js
// @errors: 7006 2554
class Todo {
done = $state(false);
text = $state();
constructor(text) {
this.text = text;
}
reset() {
this.text = '';
this.done = false;
}
}
```
> In this example, the compiler transforms `done` and `text` into `get`/`set` methods on the class prototype referencing private fields
Objects and arrays are made deeply reactive by wrapping them with [`Proxies`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy). What that means is that in the following example, we can mutate the `entries` object and the UI will still update - but only the list item that is actually changed will rerender:
```svelte
<script>
let entries = $state([
{ id: 1, text: 'foo' },
{ id: 2, text: 'bar' }
]);
</script>
{#each entries as entry (entry.id)}
{entry.text}
{/each}
<button onclick={() => (entries[1].text = 'baz')}>change second entry text</button>
```
> Only POJOs (plain of JavaScript objects) are made deeply reactive. Reactivity will stop at class boundaries and leave those alone
## `$state.frozen`
State declared with `$state.frozen` cannot be mutated; it can only be _reassigned_. In other words, rather than assigning to a property of an object, or using an array method like `push`, replace the object or array altogether if you'd like to update it:
```svelte
<script>
let entries = $state([
{ id: 1, text: 'foo' },
{ id: 2, text: 'bar' }
]);
</script>
{#each entries as entry (entry.id)}
{entry.text}
{/each}
<button onclick={() => (entries = [entries[0], { id: entries[1].id, text: 'baz' }])}
>change second entry text</button
>
```
This can improve performance with large arrays and objects that you weren't planning to mutate anyway, since it avoids the cost of making them reactive. Note that frozen state can _contain_ reactive state (for example, a frozen array of reactive objects).
> Objects and arrays passed to `$state.frozen` will be shallowly frozen using `Object.freeze()`. If you don't want this, pass in a clone of the object or array instead.
## `$state.snapshot`
To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snapshot`:
```svelte
<script>
let counter = $state({ count: 0 });
function onclick() {
// Will log `{ count: ... }` rather than `Proxy { ... }`
console.log($state.snapshot(counter));
}
</script>
```
This is handy when you want to pass some state to an external library or API that doesn't expect a proxy, such as `structuredClone`.
> Note that `$state.snapshot` will clone the data when removing reactivity. If the value passed isn't a `$state` proxy, it will be returned as-is.
## `$state.is`
Sometimes you might need to compare two values, one of which is a reactive `$state(...)` proxy but the other is not. For this you can use `$state.is(a, b)`:
```svelte
<script>
let foo = $state({});
let bar = {};
foo.bar = bar;
console.log(foo.bar === bar); // false — `foo.bar` is a reactive proxy
console.log($state.is(foo.bar, bar)); // true
</script>
```
This is handy when you might want to check if the object exists within a deeply reactive object/array.
Under the hood, `$state.is` uses [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) for comparing the values.
> Use this as an escape hatch - most of the time you don't need this. Svelte will warn you at dev time if you happen to run into this problem
## `$derived`
Derived state is declared with the `$derived` rune:
```svelte
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<button onclick={() => count++}>
{doubled}
</button>
<p>{count} doubled is {doubled}</p>
```
The expression inside `$derived(...)` should be free of side-effects. Svelte will disallow state changes (e.g. `count++`) inside derived expressions.
As with `$state`, you can mark class fields as `$derived`.
## `$derived.by`
Sometimes you need to create complex derivations that don't fit inside a short expression. In these cases, you can use `$derived.by` which accepts a function as its argument.
```svelte
<script>
let numbers = $state([1, 2, 3]);
let total = $derived.by(() => {
let total = 0;
for (const n of numbers) {
total += n;
}
return total;
});
</script>
<button onclick={() => numbers.push(numbers.length + 1)}>
{numbers.join(' + ')} = {total}
</button>
```
In essence, `$derived(expression)` is equivalent to `$derived.by(() => expression)`.
## Universal reactivity
In the examples above, `$state` and `$derived` only appear at the top level of components. You can also use them within functions or even outside Svelte components inside `.svelte.js` or `.svelte.ts` modules.
```ts
/// file: counter.svelte.ts
export function createCounter(initial: number) {
let count = $state(initial);
let double = $derived(count * 2);
return {
get count() {
return count;
},
get double() {
return double;
},
increment: () => count++
};
}
```
```svelte
<!--- file: App.svelte --->
<script>
import { createCounter } from './counter.svelte';
const counter = createCounter();
</script>
<button onclick={counter.increment}>{counter.count} / {counter.double}</button>
```
There are a few things to note in the above example:
- We're using getters to transport reactivity across the function boundary. This way we keep reactivity "alive". If we were to return the value itself, it would be fixed to the value at that point in time. This is no different to how regular JavaScript variables behave.
- We're not destructuring the counter at the usage site. Because we're using getters, destructuring would fix `count` and `double` to the value at that point in time. To keep the getters "alive", we're not using destructuring. Again, this is how regular JavaScript works.
If you have shared state you want to manipulate from various places, you don't need to resort to getters. Instead, you can take advantage of `$state` being deeply reactive and only update its properties, not the value itself:
```ts
/// file: app-state.svelte.ts
export const appState = $state({
loggedIn: true
});
```
```svelte
<!--- file: App.svelte --->
<script>
import { appState } from './app-state.svelte';
</script>
<button onclick={() => (appState.loggedIn = false)}>Log out</button>
```

@ -0,0 +1,360 @@
---
title: Side effects
---
- `$effect` (.pre)
- when not to use it, better patterns for what to do instead
Side effects play a crucial role in applications. They are triggered by state changes and can then interact with external systems, like logging something, setting up a server connection or synchronize with a third-party library that has no knowledge of Svelte's reactivity model.
## `$effect` fundamentals
To run _side-effects_ when the component is mounted to the DOM, and when values change, we can use the `$effect` rune ([demo](/#H4sIAAAAAAAAE31T24rbMBD9lUG7kAQ2sbdlX7xOYNk_aB_rQhRpbAsU2UiTW0P-vbrYubSlYGzmzMzROTPymdVKo2PFjzMzfIusYB99z14YnfoQuD1qQh-7bmdFQEonrOppVZmKNBI49QthCc-OOOH0LZ-9jxnR6c7eUpOnuv6KeT5JFdcqbvbcBcgDz1jXKGg6ncFyBedYR6IzLrAZwiN5vtSxaJA-EzadfJEjKw11C6GR22-BLH8B_wxdByWpvUYtqqal2XB6RVkG1CoHB6U1WJzbnYFDiwb3aGEdDa3Bm1oH12sQLTcNPp7r56m_00mHocSG97_zd7ICUXonA5fwKbPbkE2ZtMJGGVkEdctzQi4QzSwr9prnFYNk5hpmqVuqPQjNnfOJoMF22lUsrq_UfIN6lfSVyvQ7grB3X2mjMZYO3XO9w-U5iLx42qg29md3BP_ni5P4gy9ikTBlHxjLzAtPDlyYZmRdjAbGq7HprEQ7p64v4LU_guu0kvAkhBim3nMplWl8FreQD-CW20aZR0wq12t-KqDWeBywhvexKC3memmDwlHAv9q4Vo2ZK8KtK0CgX7u9J8wXbzdKv-nRnfF_2baTqlYoWUF2h5efl9-n0O6koAMAAA==)):
```svelte
<script>
let size = $state(50);
let color = $state('#ff3e00');
let canvas;
$effect(() => {
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
// this will re-run whenever `color` or `size` change
context.fillStyle = color;
context.fillRect(0, 0, size, size);
});
</script>
<canvas bind:this={canvas} width="100" height="100" />
```
The function passed to `$effect` will run when the component mounts, and will re-run after any changes to the values it reads that were declared with `$state` or `$derived` (including those passed in with `$props`). Re-runs are batched (i.e. changing `color` and `size` in the same moment won't cause two separate runs), and happen after any DOM updates have been applied.
You can return a function from `$effect`, which will run immediately before the effect re-runs, and before it is destroyed ([demo](/#H4sIAAAAAAAAE42SzW6DMBCEX2Vl5RDaVCQ9JoDUY--9lUox9lKsGBvZC1GEePcaKPnpqSe86_m0M2t6ViqNnu0_e2Z4jWzP3pqGbRhdmrHwHWrCUHvbOjF2Ei-caijLTU4aCYRtDUEKK0-ccL2NDstNrbRWHoU10t8Eu-121gTVCssSBa3XEaQZ9GMrpziGj0p5OAccCgSHwmEgJZwrNNihg6MyhK7j-gii4uYb_YyGUZ5guQwzPdL7b_U4ZNSOvp9T2B3m1rB5cLx4zMkhtc7AHz7YVCVwEFzrgosTBMuNs52SKDegaPbvWnMH8AhUXaNUIY6-hHCldQhUIcyLCFlfAuHvkCKaYk8iYevGGgy2wyyJnpy9oLwG0sjdNe2yhGhJN32HsUzi2xOapNpl_bSLIYnDeeoVLZE1YI3QSpzSfo7-8J5PKbwOmdf2jC6JZyD7HxpPaMk93aHhF6utVKVCyfbkWhy-hh9Z3o_2nQIAAA==)).
```svelte
<script>
let count = $state(0);
let milliseconds = $state(1000);
$effect(() => {
// This will be recreated whenever `milliseconds` changes
const interval = setInterval(() => {
count += 1;
}, milliseconds);
return () => {
// if a callback is provided, it will run
// a) immediately before the effect re-runs
// b) when the component is destroyed
clearInterval(interval);
};
});
</script>
<h1>{count}</h1>
<button onclick={() => (milliseconds *= 2)}>slower</button>
<button onclick={() => (milliseconds /= 2)}>faster</button>
```
## `$effect` dependencies
`$effect` automatically picks up any reactivy values (`$state`, `$derived`, `$props`) that are _synchronously_ read inside its function body and registers them as dependencies. When those dependencies change, the `$effect` schedules a rerun.
Values that are read asynchronously — after an `await` or inside a `setTimeout`, for example — will _not_ be tracked. Here, the canvas will be repainted when `color` changes, but not when `size` changes ([demo](/#H4sIAAAAAAAAE31T24rbMBD9lUG7kCxsbG_LvrhOoPQP2r7VhSjy2BbIspHGuTT436tLnMtSCiaOzpw5M2dGPrNaKrQs_3VmmnfIcvZ1GNgro9PgD3aPitCdbT8a4ZHCCiMH2pS6JIUEVv5BWMOzJU64fM9evswR0ave3EKLp7r-jFm2iIwri-s9tx5ywDPWNQpaLl9gvYFz4JHotfVqmvBITi9mJA3St4gtF5-qWZUuvEQo5Oa7F8tewT2XrIOsqL2eWpRNS7eGSkpToFZaOEilwODKjBoOLWrco4FtsLQF0XLdoE2S5LGmm6X6QSflBxKod8IW6afssB8_uAslndJuJNA9hWKw9VO91pmJ92XunHlu_J1nMDk8_p_8q0hvO9NFtA47qavcW12fIzJBmM26ZG9ZVjKIs7ke05hdyT0Ixa11Ad-P6ZUtWbgNheI7VJvYQiH14Bz5a-SYxvtwIqHonqsR12ff8ORkQ-chP70T-L9eGO4HvYAFwRh9UCxS13h0YP2CgmoyG5h3setNhWZF_ZDD23AE2ytZwZMQ4jLYgVeV1I2LYgfZBey4aaR-xCppB8VPOdQKjxes4UMgxcVcvwHf4dzAv9K4ko1eScLO5iDQXQFzL5gl7zdJt-nZnXYfbddXspZYsZzMiNPv6S8Bl41G7wMAAA==)):
```ts
// @filename: index.ts
declare let canvas: {
width: number;
height: number;
getContext(type: '2d', options?: CanvasRenderingContext2DSettings): CanvasRenderingContext2D;
};
declare let color: string;
declare let size: number;
// ---cut---
$effect(() => {
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
// this will re-run whenever `color` changes...
context.fillStyle = color;
setTimeout(() => {
// ...but not when `size` changes
context.fillRect(0, 0, size, size);
}, 0);
});
```
An effect only reruns when the object it reads changes, not when a property inside it changes. (If you want to observe changes _inside_ an object at dev time, you can use [`$inspect`](/docs/svelte/misc/debugging#$inspect).)
```svelte
<script>
let state = $state({ value: 0 });
let derived = $derived({ value: state.value * 2 });
// this will run once, because `state` is never reassigned (only mutated)
$effect(() => {
state;
});
// this will run whenever `state.value` changes...
$effect(() => {
state.value;
});
// ...and so will this, because `derived` is a new object each time
$effect(() => {
derived;
});
</script>
<button onclick={() => (state.value += 1)}>
{state.value}
</button>
<p>{state.value} doubled is {derived.value}</p>
```
## When not to use `$effect`
In general, `$effect` is best considered something of an escape hatch — useful for things like analytics and direct DOM manipulation — rather than a tool you should use frequently. In particular, avoid using it to synchronise state. Instead of this...
```svelte
<script>
let count = $state(0);
let doubled = $state();
// don't do this!
$effect(() => {
doubled = count * 2;
});
</script>
```
...do this:
```svelte
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
```
> For things that are more complicated than a simple expression like `count * 2`, you can also use [`$derived.by`](#$derived-by).
You might be tempted to do something convoluted with effects to link one value to another. The following example shows two inputs for "money spent" and "money left" that are connected to each other. If you update one, the other should update accordingly. Don't use effects for this ([demo](/#H4sIAAAAAAAACpVRy2rDMBD8lWXJwYE0dg-9KFYg31H3oNirIJBlYa1DjPG_F8l1XEop9LgzOzP7mFAbSwHF-4ROtYQCL97jAXn0sQh3skx4wNANfR2RMtS98XyuXMWWGLhjZUHCa1GcVix4cgwSdoEVU1bsn4wl_Y1I2kS6inekNdWcZXuQZ5giFDWpfwl5WYyT2fynbB1g1UWbTVbm2w6utOpKNq1TGucHhri6rLBX7kYVwtW4RtyVHUhOyXeGVj3klLxnyJP0i8lXNJUx6en-v6A48K85kTimpi0sYj-yAo-Wlh9FcL1LY4K3ahSgLT1OC3ZTXkBxfKN2uVC6T5LjAduuMdpQg4L7geaP-RNHPuClMQIAAA==)):
```svelte
<script>
let total = 100;
let spent = $state(0);
let left = $state(total);
$effect(() => {
left = total - spent;
});
$effect(() => {
spent = total - left;
});
</script>
<label>
<input type="range" bind:value={spent} max={total} />
{spent}/{total} spent
</label>
<label>
<input type="range" bind:value={left} max={total} />
{left}/{total} left
</label>
```
Instead, use callbacks where possible ([demo](/#H4sIAAAAAAAACo2SP2-DMBDFv8rp1CFR84cOXQhU6p6tY-ngwoEsGWPhI0pk8d0rG5yglqGj37v7veMJh7VUZDH9dKhFS5jiuzG4Q74Z_7AXUky4Q9sNfemVzJa9NPxW6IIVMXDHQkEOL0lyipo1pBlyeLIsmDbJ9u4oqhdG2A2mLrgedMmy0zCYSjB9eMaGtuC8WXBkPtOBRd8QHy5CDXSa3Jk7HbOfDgjWuAo_U71kz9vr6Bgc2X44orPjow2dKfFNKhSTSW0GBl9iXmAvdEMFQqDmLgBH6HQYyt3ie0doxTV3IWqEY2DN88eohqePvsf9O9mf_if4HMSVXD89NfEI99qvbMs3RdPv4MXYaSWtUeKWQq3oOlfZCJNCcnildlFgWMcdtl0la0kVptwPNH6NP_uzV0acAgAA)):
```svelte
<script>
let total = 100;
let spent = $state(0);
let left = $state(total);
function updateSpent(e) {
spent = +e.target.value;
left = total - spent;
}
function updateLeft(e) {
left = +e.target.value;
spent = total - left;
}
</script>
<label>
<input type="range" value={spent} oninput={updateSpent} max={total} />
{spent}/{total} spent
</label>
<label>
<input type="range" value={left} oninput={updateLeft} max={total} />
{left}/{total} left
</label>
```
If you need to use bindings, for whatever reason (for example when you want some kind of "writable `$derived`"), consider using getters and setters to synchronise state ([demo](/#H4sIAAAAAAAACo2SQW-DMAyF_4pl7dBqXcsOu1CYtHtvO44dsmKqSCFExFRFiP8-xRCGth52tJ_9PecpA1bakMf0Y0CrasIU35zDHXLvQuGvZJhwh77p2nPoZP7casevhS3YEAM3rAzk8Jwkx9jzjixDDg-eFdMm2S6KoWolyK6ItuCqs2fWjYXOlYrpPTA2tIUhiAVH5iPtWbUX4v1VmY6Okzpzp2OepgNEGu_CT1St2fP2fXQ0juwwHNHZ4ScNmxn1RUaCybR1HUMIMS-wVfZCBYJQ80GAIzRWhvJh9d4RanXLB7Ea4SCsef4Qu1IG68Xu387h9D_GJ2ne8ZXpxTZUv1w994amjxCaMc1Se2dUn0Jl6DaHeFEuhWT_QvUqOlnHHdZNqStNJabcdjR-jt8IbC-7lgIAAA==)):
```svelte
<script>
let total = 100;
let spent = $state(0);
let left = {
get value() {
return total - spent;
},
set value(v) {
spent = total - v;
}
};
</script>
<label>
<input type="range" bind:value={spent} max={total} />
{spent}/{total} spent
</label>
<label>
<input type="range" bind:value={left.value} max={total} />
{left.value}/{total} left
</label>
```
If you absolutely have to update `$state` within an effect and run into an infinite loop because you read and write to the same `$state`, use [untrack](functions#untrack).
## `$effect.pre`
In rare cases, you may need to run code _before_ the DOM updates. For this we can use the `$effect.pre` rune:
```svelte
<script>
import { tick } from 'svelte';
let div;
let messages = [];
// ...
$effect.pre(() => {
if (!div) return; // not yet mounted
// reference `messages` so that this code re-runs whenever it changes
messages;
// autoscroll when new messages are added
if (div.offsetHeight + div.scrollTop > div.scrollHeight - 20) {
tick().then(() => {
div.scrollTo(0, div.scrollHeight);
});
}
});
</script>
<div bind:this={div}>
{#each messages as message}
<p>{message}</p>
{/each}
</div>
```
Apart from the timing, `$effect.pre` works exactly like [`$effect`](#$effect) — refer to its documentation for more info.
## `$effect.tracking`
The `$effect.tracking` rune is an advanced feature that tells you whether or not the code is running inside a tracking context, such as an effect or inside your template ([demo](/#H4sIAAAAAAAAE3XP0QrCMAwF0F-JRXAD595rLfgdzodRUyl0bVgzQcb-3VYFQfExl5tDMgvrPCYhT7MI_YBCiiOR2Aq-UxnSDT1jnlOcRlMSlczoiHUXOjYxpOhx5-O12rgAJg4UAwaGhDyR3Gxhjdai4V1v2N2wqus9tC3Y3ifMQjbehaqq4aBhLtEv_Or893icCsdLve-Caj8nBkU67zMO5HtGCfM3sKiWNKhV0zwVaBqd3x3ixVmHFyFLuJyXB-moOe8pAQAA)):
```svelte
<script>
console.log('in component setup:', $effect.tracking()); // false
$effect(() => {
console.log('in effect:', $effect.tracking()); // true
});
</script>
<p>in template: {$effect.tracking()}</p> <!-- true -->
```
This allows you to (for example) add things like subscriptions without causing memory leaks, by putting them in child effects. Here's a `readable` function that listens to changes from a callback function as long as it's inside a tracking context:
```ts
import { tick } from 'svelte';
export default function readable<T>(
initial_value: T,
start: (callback: (update: (v: T) => T) => T) => () => void
) {
let value = $state(initial_value);
let subscribers = 0;
let stop: null | (() => void) = null;
return {
get value() {
// If in a tracking context ...
if ($effect.tracking()) {
$effect(() => {
// ...and there's no subscribers yet...
if (subscribers === 0) {
// ...invoke the function and listen to changes to update state
stop = start((fn) => (value = fn(value)));
}
subscribers++;
// The return callback is called once a listener unlistens
return () => {
tick().then(() => {
subscribers--;
// If it was the last subscriber...
if (subscribers === 0) {
// ...stop listening to changes
stop?.();
stop = null;
}
});
};
});
}
return value;
}
};
}
```
## `$effect.root`
The `$effect.root` rune is an advanced feature that creates a non-tracked scope that doesn't auto-cleanup. This is useful for
nested effects that you want to manually control. This rune also allows for creation of effects outside of the component initialisation phase.
```svelte
<script>
let count = $state(0);
const cleanup = $effect.root(() => {
$effect(() => {
console.log(count);
});
return () => {
console.log('effect root cleanup');
};
});
</script>
```

@ -0,0 +1,3 @@
---
title: Runes
---

@ -1,230 +0,0 @@
---
title: svelte
---
The `svelte` package exposes [lifecycle functions](https://learn.svelte.dev/tutorial/onmount) and the [context API](https://learn.svelte.dev/tutorial/context-api).
## `onMount`
> EXPORT_SNIPPET: svelte#onMount
The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM. It must be called during the component's initialisation (but doesn't need to live _inside_ the component; it can be called from an external module).
`onMount` does not run inside a [server-side component](/docs/server-side-component-api).
```svelte
<script>
import { onMount } from 'svelte';
onMount(() => {
console.log('the component has mounted');
});
</script>
```
If a function is returned from `onMount`, it will be called when the component is unmounted.
```svelte
<script>
import { onMount } from 'svelte';
onMount(() => {
const interval = setInterval(() => {
console.log('beep');
}, 1000);
return () => clearInterval(interval);
});
</script>
```
> This behaviour will only work when the function passed to `onMount` _synchronously_ returns a value. `async` functions always return a `Promise`, and as such cannot _synchronously_ return a function.
## `beforeUpdate`
> EXPORT_SNIPPET: svelte#beforeUpdate
Schedules a callback to run immediately before the component is updated after any state change.
> The first time the callback runs will be before the initial `onMount`
```svelte
<script>
import { beforeUpdate } from 'svelte';
beforeUpdate(() => {
console.log('the component is about to update');
});
</script>
```
## `afterUpdate`
> EXPORT_SNIPPET: svelte#afterUpdate
Schedules a callback to run immediately after the component has been updated.
> The first time the callback runs will be after the initial `onMount`
```svelte
<script>
import { afterUpdate } from 'svelte';
afterUpdate(() => {
console.log('the component just updated');
});
</script>
```
## `onDestroy`
> EXPORT_SNIPPET: svelte#onDestroy
Schedules a callback to run immediately before the component is unmounted.
Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the only one that runs inside a server-side component.
```svelte
<script>
import { onDestroy } from 'svelte';
onDestroy(() => {
console.log('the component is being destroyed');
});
</script>
```
## `tick`
> EXPORT_SNIPPET: svelte#tick
Returns a promise that resolves once any pending state changes have been applied, or in the next microtask if there are none.
```svelte
<script>
import { beforeUpdate, tick } from 'svelte';
beforeUpdate(async () => {
console.log('the component is about to update');
await tick();
console.log('the component just updated');
});
</script>
```
## `setContext`
> EXPORT_SNIPPET: svelte#setContext
Associates an arbitrary `context` object with the current component and the specified `key` and returns that object. The context is then available to children of the component (including slotted content) with `getContext`.
Like lifecycle functions, this must be called during component initialisation.
```svelte
<script>
import { setContext } from 'svelte';
setContext('answer', 42);
</script>
```
> Context is not inherently reactive. If you need reactive values in context then you can pass a store into context, which _will_ be reactive.
## `getContext`
> EXPORT_SNIPPET: svelte#getContext
Retrieves the context that belongs to the closest parent component with the specified `key`. Must be called during component initialisation.
```svelte
<script>
import { getContext } from 'svelte';
const answer = getContext('answer');
</script>
```
## `hasContext`
> EXPORT_SNIPPET: svelte#hasContext
Checks whether a given `key` has been set in the context of a parent component. Must be called during component initialisation.
```svelte
<script>
import { hasContext } from 'svelte';
if (hasContext('answer')) {
// do something
}
</script>
```
## `getAllContexts`
> EXPORT_SNIPPET: svelte#getAllContexts
Retrieves the whole context map that belongs to the closest parent component. Must be called during component initialisation. Useful, for example, if you programmatically create a component and want to pass the existing context to it.
```svelte
<script>
import { getAllContexts } from 'svelte';
const contexts = getAllContexts();
</script>
```
## `createEventDispatcher`
> EXPORT_SNIPPET: svelte#createEventDispatcher
Creates an event dispatcher that can be used to dispatch [component events](/docs/component-directives#on-eventname). Event dispatchers are functions that can take two arguments: `name` and `detail`.
Component events created with `createEventDispatcher` create a [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent). These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture). The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail) property and can contain any type of data.
```svelte
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
</script>
<button on:click={() => dispatch('notify', 'detail value')}>Fire Event</button>
```
Events dispatched from child components can be listened to in their parent. Any data provided when the event was dispatched is available on the `detail` property of the event object.
```svelte
<script>
function callbackFunction(event) {
console.log(`Notify fired! Detail: ${event.detail}`);
}
</script>
<Child on:notify={callbackFunction} />
```
Events can be cancelable by passing a third parameter to the dispatch function. The function returns `false` if the event is cancelled with `event.preventDefault()`, otherwise it returns `true`.
```svelte
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
function notify() {
const shouldContinue = dispatch('notify', 'detail value', { cancelable: true });
if (shouldContinue) {
// no one called preventDefault
} else {
// a listener called preventDefault
}
}
</script>
```
You can type the event dispatcher to define which events it can receive. This will make your code more type safe both within the component (wrong calls are flagged) and when using the component (types of the events are now narrowed). See [here](typescript#script-lang-ts-events) how to do it.
## Types
> TYPES: svelte

@ -1,169 +0,0 @@
---
title: 'svelte/motion'
---
The `svelte/motion` module exports two functions, `tweened` and `spring`, for creating writable stores whose values change over time after `set` and `update`, rather than immediately.
## `tweened`
> EXPORT_SNIPPET: svelte/motion#tweened
Tweened stores update their values over a fixed duration. The following options are available:
- `delay` (`number`, default 0) — milliseconds before starting
- `duration` (`number` | `function`, default 400) — milliseconds the tween lasts
- `easing` (`function`, default `t => t`) — an [easing function](/docs/svelte-easing)
- `interpolate` (`function`) — see below
`store.set` and `store.update` can accept a second `options` argument that will override the options passed in upon instantiation.
Both functions return a Promise that resolves when the tween completes. If the tween is interrupted, the promise will never resolve.
Out of the box, Svelte will interpolate between two numbers, two arrays or two objects (as long as the arrays and objects are the same 'shape', and their 'leaf' properties are also numbers).
```svelte
<script>
import { tweened } from 'svelte/motion';
import { cubicOut } from 'svelte/easing';
const size = tweened(1, {
duration: 300,
easing: cubicOut
});
function handleClick() {
// this is equivalent to size.update(n => n + 1)
$size += 1;
}
</script>
<button on:click={handleClick} style="transform: scale({$size}); transform-origin: 0 0">
embiggen
</button>
```
If the initial value is `undefined` or `null`, the first value change will take effect immediately. This is useful when you have tweened values that are based on props, and don't want any motion when the component first renders.
```ts
// @filename: ambient.d.ts
declare global {
var $size: number;
var big: number;
}
export {};
// @filename: motion.ts
// ---cut---
import { tweened } from 'svelte/motion';
import { cubicOut } from 'svelte/easing';
const size = tweened(undefined, {
duration: 300,
easing: cubicOut
});
$: $size = big ? 100 : 10;
```
The `interpolate` option allows you to tween between _any_ arbitrary values. It must be an `(a, b) => t => value` function, where `a` is the starting value, `b` is the target value, `t` is a number between 0 and 1, and `value` is the result. For example, we can use the [d3-interpolate](https://github.com/d3/d3-interpolate) package to smoothly interpolate between two colours.
```svelte
<script>
import { interpolateLab } from 'd3-interpolate';
import { tweened } from 'svelte/motion';
const colors = ['rgb(255, 62, 0)', 'rgb(64, 179, 255)', 'rgb(103, 103, 120)'];
const color = tweened(colors[0], {
duration: 800,
interpolate: interpolateLab
});
</script>
{#each colors as c}
<button style="background-color: {c}; color: white; border: none;" on:click={(e) => color.set(c)}>
{c}
</button>
{/each}
<h1 style="color: {$color}">{$color}</h1>
```
## `spring`
> EXPORT_SNIPPET: svelte/motion#spring
A `spring` store gradually changes to its target value based on its `stiffness` and `damping` parameters. Whereas `tweened` stores change their values over a fixed duration, `spring` stores change over a duration that is determined by their existing velocity, allowing for more natural-seeming motion in many situations. The following options are available:
- `stiffness` (`number`, default `0.15`) — a value between 0 and 1 where higher means a 'tighter' spring
- `damping` (`number`, default `0.8`) — a value between 0 and 1 where lower means a 'springier' spring
- `precision` (`number`, default `0.01`) — determines the threshold at which the spring is considered to have 'settled', where lower means more precise
All of the options above can be changed while the spring is in motion, and will take immediate effect.
```js
import { spring } from 'svelte/motion';
const size = spring(100);
size.stiffness = 0.3;
size.damping = 0.4;
size.precision = 0.005;
```
As with [`tweened`](/docs/svelte-motion#tweened) stores, `set` and `update` return a Promise that resolves if the spring settles.
Both `set` and `update` can take a second argument — an object with `hard` or `soft` properties. `{ hard: true }` sets the target value immediately; `{ soft: n }` preserves existing momentum for `n` seconds before settling. `{ soft: true }` is equivalent to `{ soft: 0.5 }`.
```js
import { spring } from 'svelte/motion';
const coords = spring({ x: 50, y: 50 });
// updates the value immediately
coords.set({ x: 100, y: 200 }, { hard: true });
// preserves existing momentum for 1s
coords.update(
(target_coords, coords) => {
return { x: target_coords.x, y: coords.y };
},
{ soft: 1 }
);
```
[See a full example on the spring tutorial.](https://learn.svelte.dev/tutorial/springs)
```svelte
<script>
import { spring } from 'svelte/motion';
const coords = spring(
{ x: 50, y: 50 },
{
stiffness: 0.1,
damping: 0.25
}
);
</script>
```
If the initial value is `undefined` or `null`, the first value change will take effect immediately, just as with `tweened` values (see above).
```ts
// @filename: ambient.d.ts
declare global {
var $size: number;
var big: number;
}
export {};
// @filename: motion.ts
// ---cut---
import { spring } from 'svelte/motion';
const size = spring();
$: $size = big ? 100 : 10;
```
## Types
> TYPES: svelte/motion

@ -1,300 +0,0 @@
---
title: 'svelte/transition'
---
The `svelte/transition` module exports seven functions: `fade`, `blur`, `fly`, `slide`, `scale`, `draw` and `crossfade`. They are for use with Svelte [`transitions`](/docs/element-directives#transition-fn).
## `fade`
> EXPORT_SNIPPET: svelte/transition#fade
```svelte
<!--- copy: false --->
transition:fade={params}
```
```svelte
<!--- copy: false --->
in:fade={params}
```
```svelte
<!--- copy: false --->
out:fade={params}
```
Animates the opacity of an element from 0 to the current opacity for `in` transitions and from the current opacity to 0 for `out` transitions.
`fade` accepts the following parameters:
- `delay` (`number`, default 0) — milliseconds before starting
- `duration` (`number`, default 400) — milliseconds the transition lasts
- `easing` (`function`, default `linear`) — an [easing function](/docs/svelte-easing)
You can see the `fade` transition in action in the [transition tutorial](https://learn.svelte.dev/tutorial/transition).
```svelte
<script>
import { fade } from 'svelte/transition';
</script>
{#if condition}
<div transition:fade={{ delay: 250, duration: 300 }}>fades in and out</div>
{/if}
```
## `blur`
> EXPORT_SNIPPET: svelte/transition#blur
```svelte
<!--- copy: false --->
transition:blur={params}
```
```svelte
<!--- copy: false --->
in:blur={params}
```
```svelte
<!--- copy: false --->
out:blur={params}
```
Animates a `blur` filter alongside an element's opacity.
`blur` accepts the following parameters:
- `delay` (`number`, default 0) — milliseconds before starting
- `duration` (`number`, default 400) — milliseconds the transition lasts
- `easing` (`function`, default `cubicInOut`) — an [easing function](/docs/svelte-easing)
- `opacity` (`number`, default 0) - the opacity value to animate out to and in from
- `amount` (`number | string`, default 5) - the size of the blur. Supports css units (for example: `"4rem"`). The default unit is `px`
```svelte
<script>
import { blur } from 'svelte/transition';
</script>
{#if condition}
<div transition:blur={{ amount: 10 }}>fades in and out</div>
{/if}
```
## `fly`
> EXPORT_SNIPPET: svelte/transition#fly
```svelte
<!--- copy: false --->
transition:fly={params}
```
```svelte
<!--- copy: false --->
in:fly={params}
```
```svelte
<!--- copy: false --->
out:fly={params}
```
Animates the x and y positions and the opacity of an element. `in` transitions animate from the provided values, passed as parameters to the element's default values. `out` transitions animate from the element's default values to the provided values.
`fly` accepts the following parameters:
- `delay` (`number`, default 0) — milliseconds before starting
- `duration` (`number`, default 400) — milliseconds the transition lasts
- `easing` (`function`, default `cubicOut`) — an [easing function](/docs/svelte-easing)
- `x` (`number | string`, default 0) - the x offset to animate out to and in from
- `y` (`number | string`, default 0) - the y offset to animate out to and in from
- `opacity` (`number`, default 0) - the opacity value to animate out to and in from
x and y use `px` by default but support css units, for example `x: '100vw'` or `y: '50%'`.
You can see the `fly` transition in action in the [transition tutorial](https://learn.svelte.dev/tutorial/adding-parameters-to-transitions).
```svelte
<script>
import { fly } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
</script>
{#if condition}
<div
transition:fly={{ delay: 250, duration: 300, x: 100, y: 500, opacity: 0.5, easing: quintOut }}
>
flies in and out
</div>
{/if}
```
## `slide`
> EXPORT_SNIPPET: svelte/transition#slide
```svelte
<!--- copy: false --->
transition:slide={params}
```
```svelte
<!--- copy: false --->
in:slide={params}
```
```svelte
<!--- copy: false --->
out:slide={params}
```
Slides an element in and out.
`slide` accepts the following parameters:
- `delay` (`number`, default 0) — milliseconds before starting
- `duration` (`number`, default 400) — milliseconds the transition lasts
- `easing` (`function`, default `cubicOut`) — an [easing function](/docs/svelte-easing)
* `axis` (`x` | `y`, default `y`) — the axis of motion along which the transition occurs
```svelte
<script>
import { slide } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
</script>
{#if condition}
<div transition:slide={{ delay: 250, duration: 300, easing: quintOut, axis: 'x' }}>
slides in and out horizontally
</div>
{/if}
```
## `scale`
> EXPORT_SNIPPET: svelte/transition#scale
```svelte
<!--- copy: false --->
transition:scale={params}
```
```svelte
<!--- copy: false --->
in:scale={params}
```
```svelte
<!--- copy: false --->
out:scale={params}
```
Animates the opacity and scale of an element. `in` transitions animate from an element's current (default) values to the provided values, passed as parameters. `out` transitions animate from the provided values to an element's default values.
`scale` accepts the following parameters:
- `delay` (`number`, default 0) — milliseconds before starting
- `duration` (`number`, default 400) — milliseconds the transition lasts
- `easing` (`function`, default `cubicOut`) — an [easing function](/docs/svelte-easing)
- `start` (`number`, default 0) - the scale value to animate out to and in from
- `opacity` (`number`, default 0) - the opacity value to animate out to and in from
```svelte
<script>
import { scale } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
</script>
{#if condition}
<div transition:scale={{ duration: 500, delay: 500, opacity: 0.5, start: 0.5, easing: quintOut }}>
scales in and out
</div>
{/if}
```
## `draw`
> EXPORT_SNIPPET: svelte/transition#draw
```svelte
<!--- copy: false --->
transition:draw={params}
```
```svelte
<!--- copy: false --->
in:draw={params}
```
```svelte
<!--- copy: false --->
out:draw={params}
```
Animates the stroke of an SVG element, like a snake in a tube. `in` transitions begin with the path invisible and draw the path to the screen over time. `out` transitions start in a visible state and gradually erase the path. `draw` only works with elements that have a `getTotalLength` method, like `<path>` and `<polyline>`.
`draw` accepts the following parameters:
- `delay` (`number`, default 0) — milliseconds before starting
- `speed` (`number`, default undefined) - the speed of the animation, see below.
- `duration` (`number` | `function`, default 800) — milliseconds the transition lasts
- `easing` (`function`, default `cubicInOut`) — an [easing function](/docs/svelte-easing)
The `speed` parameter is a means of setting the duration of the transition relative to the path's length. It is a modifier that is applied to the length of the path: `duration = length / speed`. A path that is 1000 pixels with a speed of 1 will have a duration of `1000ms`, setting the speed to `0.5` will double that duration and setting it to `2` will halve it.
```svelte
<script>
import { draw } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
</script>
<svg viewBox="0 0 5 5" xmlns="http://www.w3.org/2000/svg">
{#if condition}
<path
transition:draw={{ duration: 5000, delay: 500, easing: quintOut }}
d="M2 1 h1 v1 h1 v1 h-1 v1 h-1 v-1 h-1 v-1 h1 z"
fill="none"
stroke="cornflowerblue"
stroke-width="0.1px"
stroke-linejoin="round"
/>
{/if}
</svg>
```
## `crossfade`
> EXPORT_SNIPPET: svelte/transition#crossfade
The `crossfade` function creates a pair of [transitions](/docs/element-directives#transition-fn) called `send` and `receive`. When an element is 'sent', it looks for a corresponding element being 'received', and generates a transition that transforms the element to its counterpart's position and fades it out. When an element is 'received', the reverse happens. If there is no counterpart, the `fallback` transition is used.
`crossfade` accepts the following parameters:
- `delay` (`number`, default 0) — milliseconds before starting
- `duration` (`number` | `function`, default 800) — milliseconds the transition lasts
- `easing` (`function`, default `cubicOut`) — an [easing function](/docs/svelte-easing)
- `fallback` (`function`) — A fallback [transition](/docs/element-directives#transition-fn) to use for send when there is no matching element being received, and for receive when there is no element being sent.
```svelte
<script>
import { crossfade } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
const [send, receive] = crossfade({
duration: 1500,
easing: quintOut
});
</script>
{#if condition}
<h1 in:send={{ key }} out:receive={{ key }}>BIG ELEM</h1>
{:else}
<small in:send={{ key }} out:receive={{ key }}>small elem</small>
{/if}
```
## Types
> TYPES: svelte/transition

@ -1,48 +0,0 @@
---
title: 'svelte/animate'
---
The `svelte/animate` module exports one function for use with Svelte [animations](/docs/element-directives#animate-fn).
## `flip`
> EXPORT_SNIPPET: svelte/animate#flip
```svelte
<!--- copy: false --->
animate:flip={params}
```
The `flip` function calculates the start and end position of an element and animates between them, translating the `x` and `y` values. `flip` stands for [First, Last, Invert, Play](https://aerotwist.com/blog/flip-your-animations/).
`flip` accepts the following parameters:
- `delay` (`number`, default 0) — milliseconds before starting
- `duration` (`number` | `function`, default `d => Math.sqrt(d) * 120`) — see below
- `easing` (`function`, default `cubicOut`) — an [easing function](/docs/svelte-easing)
`duration` can be provided as either:
- a `number`, in milliseconds.
- a function, `distance: number => duration: number`, receiving the distance the element will travel in pixels and returning the duration in milliseconds. This allows you to assign a duration that is relative to the distance travelled by each element.
You can see a full example on the [animations tutorial](https://learn.svelte.dev/tutorial/animate).
```svelte
<script>
import { flip } from 'svelte/animate';
import { quintOut } from 'svelte/easing';
let list = [1, 2, 3];
</script>
{#each list as n (n)}
<div animate:flip={{ delay: 250, duration: 250, easing: quintOut }}>
{n}
</div>
{/each}
```
## Types
> TYPES: svelte/animate

@ -1,31 +0,0 @@
---
title: 'svelte/easing'
---
Easing functions specify the rate of change over time and are useful when working with Svelte's built-in transitions and animations as well as the tweened and spring utilities. `svelte/easing` contains 31 named exports, a `linear` ease and 3 variants of 10 different easing functions: `in`, `out` and `inOut`.
You can explore the various eases using the [ease visualiser](/examples/easing) in the [examples section](/examples).
| ease | in | out | inOut |
| ----------- | ----------- | ------------ | -------------- |
| **back** | `backIn` | `backOut` | `backInOut` |
| **bounce** | `bounceIn` | `bounceOut` | `bounceInOut` |
| **circ** | `circIn` | `circOut` | `circInOut` |
| **cubic** | `cubicIn` | `cubicOut` | `cubicInOut` |
| **elastic** | `elasticIn` | `elasticOut` | `elasticInOut` |
| **expo** | `expoIn` | `expoOut` | `expoInOut` |
| **quad** | `quadIn` | `quadOut` | `quadInOut` |
| **quart** | `quartIn` | `quartOut` | `quartInOut` |
| **quint** | `quintIn` | `quintOut` | `quintInOut` |
| **sine** | `sineIn` | `sineOut` | `sineInOut` |
<!-- TODO -->
<!--
<div class="max">
<iframe
title="Aphrodite example"
src="/repl/easing"
scrolling="no"
></iframe>
</div> -->

@ -1,3 +0,0 @@
{
"title": "Runtime"
}

@ -1,302 +0,0 @@
---
title: 'svelte/compiler'
---
Typically, you won't interact with the Svelte compiler directly, but will instead integrate it into your build system using a bundler plugin. The bundler plugin that the Svelte team most recommends and invests in is [vite-plugin-svelte](https://github.com/sveltejs/vite-plugin-svelte). The [SvelteKit](https://kit.svelte.dev/) framework provides a setup leveraging `vite-plugin-svelte` to build applications as well as a [tool for packaging Svelte component libraries](https://kit.svelte.dev/docs/packaging). Svelte Society maintains a list of [other bundler plugins](https://sveltesociety.dev/tools/#bundling) for additional tools like Rollup and Webpack.
Nonetheless, it's useful to understand how to use the compiler, since bundler plugins generally expose compiler options to you.
## compile
> EXPORT_SNIPPET: svelte/compiler#compile
This is where the magic happens. `svelte.compile` takes your component source code, and turns it into a JavaScript module that exports a class.
```js
// @filename: ambient.d.ts
declare global {
var source: string
}
export {}
// @filename: index.ts
// ---cut---
import { compile } from 'svelte/compiler';
const result = compile(source, {
// options
});
```
Refer to [CompileOptions](#types-compileoptions) for all the available options.
The returned `result` object contains the code for your component, along with useful bits of metadata.
```ts
// @filename: ambient.d.ts
declare global {
const source: string;
}
export {};
// @filename: main.ts
import { compile } from 'svelte/compiler';
// ---cut---
const { js, css, ast, warnings, vars, stats } = compile(source);
```
Refer to [CompileResult](#types-compileresult) for a full description of the compile result.
## parse
> EXPORT_SNIPPET: svelte/compiler#parse
The `parse` function parses a component, returning only its abstract syntax tree. Unlike compiling with the `generate: false` option, this will not perform any validation or other analysis of the component beyond parsing it. Note that the returned AST is not considered public API, so breaking changes could occur at any point in time.
```js
// @filename: ambient.d.ts
declare global {
var source: string;
}
export {};
// @filename: main.ts
// ---cut---
import { parse } from 'svelte/compiler';
const ast = parse(source, { filename: 'App.svelte' });
```
## preprocess
> EXPORT_SNIPPET: svelte/compiler#preprocess
A number of [official and community-maintained preprocessing plugins](https://sveltesociety.dev/tools#preprocessors) are available to allow you to use Svelte with tools like TypeScript, PostCSS, SCSS, and Less.
You can write your own preprocessor using the `svelte.preprocess` API.
The `preprocess` function provides convenient hooks for arbitrarily transforming component source code. For example, it can be used to convert a `<style lang="sass">` block into vanilla CSS.
The first argument is the component source code. The second is an array of _preprocessors_ (or a single preprocessor, if you only have one), where a preprocessor is an object with a `name` which is required, and `markup`, `script` and `style` functions, each of which is optional.
The `markup` function receives the entire component source text, along with the component's `filename` if it was specified in the third argument.
The `script` and `style` functions receive the contents of `<script>` and `<style>` elements respectively (`content`) as well as the entire component source text (`markup`). In addition to `filename`, they get an object of the element's attributes.
Each `markup`, `script` or `style` function must return an object (or a Promise that resolves to an object) with a `code` property, representing the transformed source code. Optionally they can return an array of `dependencies` which represents files to watch for changes, and a `map` object which is a sourcemap mapping back the transformation to the original code. `script` and `style` preprocessors can optionally return a record of attributes which represent the updated attributes on the script/style tag.
> Preprocessor functions should return a `map` object whenever possible or else debugging becomes harder as stack traces can't link to the original code correctly.
```ts
// @filename: ambient.d.ts
declare global {
var source: string;
}
export {};
// @filename: main.ts
// ---cut---
import { preprocess } from 'svelte/compiler';
import MagicString from 'magic-string';
const { code } = await preprocess(
source,
{
markup: ({ content, filename }) => {
const pos = content.indexOf('foo');
if (pos < 0) {
return { code: content };
}
const s = new MagicString(content, { filename });
s.overwrite(pos, pos + 3, 'bar', { storeName: true });
return {
code: s.toString(),
map: s.generateMap()
};
}
},
{
filename: 'App.svelte'
}
);
```
If a `dependencies` array is returned, it will be included in the result object. This is used by packages like [vite-plugin-svelte](https://github.com/sveltejs/vite-plugin-svelte) and [rollup-plugin-svelte](https://github.com/sveltejs/rollup-plugin-svelte) to watch additional files for changes, in the case where your `<style>` tag has an `@import` (for example).
```ts
/// file: preprocess-sass.js
// @filename: ambient.d.ts
declare global {
var source: string;
}
export {};
// @filename: main.ts
// @errors: 2322 2345 2339
/// <reference types="@types/node" />
// ---cut---
import { preprocess } from 'svelte/compiler';
import MagicString from 'magic-string';
import sass from 'sass';
import { dirname } from 'path';
const { code } = await preprocess(
source,
{
name: 'my-fancy-preprocessor',
markup: ({ content, filename }) => {
// Return code as is when no foo string present
const pos = content.indexOf('foo');
if (pos < 0) {
return;
}
// Replace foo with bar using MagicString which provides
// a source map along with the changed code
const s = new MagicString(content, { filename });
s.overwrite(pos, pos + 3, 'bar', { storeName: true });
return {
code: s.toString(),
map: s.generateMap({ hires: true, file: filename })
};
},
style: async ({ content, attributes, filename }) => {
// only process <style lang="sass">
if (attributes.lang !== 'sass') return;
const { css, stats } = await new Promise((resolve, reject) =>
sass.render(
{
file: filename,
data: content,
includePaths: [dirname(filename)]
},
(err, result) => {
if (err) reject(err);
else resolve(result);
}
)
);
// remove lang attribute from style tag
delete attributes.lang;
return {
code: css.toString(),
dependencies: stats.includedFiles,
attributes
};
}
},
{
filename: 'App.svelte'
}
);
```
Multiple preprocessors can be used together. The output of the first becomes the input to the second. Within one preprocessor, `markup` runs first, then `script` and `style`.
> In Svelte 3, all `markup` functions ran first, then all `script` and then all `style` preprocessors. This order was changed in Svelte 4.
```js
/// file: multiple-preprocessor.js
// @errors: 2322
// @filename: ambient.d.ts
declare global {
var source: string;
}
export {};
// @filename: main.ts
// ---cut---
import { preprocess } from 'svelte/compiler';
const { code } = await preprocess(source, [
{
name: 'first preprocessor',
markup: () => {
console.log('this runs first');
},
script: () => {
console.log('this runs second');
},
style: () => {
console.log('this runs third');
}
},
{
name: 'second preprocessor',
markup: () => {
console.log('this runs fourth');
},
script: () => {
console.log('this runs fifth');
},
style: () => {
console.log('this runs sixth');
}
}
], {
filename: 'App.svelte'
});
```
## walk
> EXPORT_SNIPPET: svelte/compiler#walk
The `walk` function provides a way to walk the abstract syntax trees generated by the parser, using the compiler's own built-in instance of [estree-walker](https://github.com/Rich-Harris/estree-walker).
The walker takes an abstract syntax tree to walk and an object with two optional methods: `enter` and `leave`. For each node, `enter` is called (if present). Then, unless `this.skip()` is called during `enter`, each of the children are traversed, and then `leave` is called on the node.
```js
/// file: compiler-walk.js
// @filename: ambient.d.ts
declare global {
var ast: import('estree').Node;
function do_something(node: import('estree').Node): void;
function do_something_else(node: import('estree').Node): void;
function should_skip_children(node: import('estree').Node): boolean;
}
export {};
// @filename: main.ts
// @errors: 7006
// ---cut---
import { walk } from 'svelte/compiler';
walk(ast, {
enter(node, parent, prop, index) {
do_something(node);
if (should_skip_children(node)) {
this.skip();
}
},
leave(node, parent, prop, index) {
do_something_else(node);
}
});
```
## VERSION
> EXPORT_SNIPPET: svelte/compiler#VERSION
The current version, as set in package.json.
```js
import { VERSION } from 'svelte/compiler';
console.log(`running svelte version ${VERSION}`);
```
## Types
> TYPES: svelte/compiler

@ -1,253 +0,0 @@
---
title: 'Client-side component API'
---
## Creating a component
```ts
// @errors: 2554
// @filename: ambient.d.ts
import { SvelteComponent, ComponentConstructorOptions } from 'svelte';
declare global {
class Component extends SvelteComponent {}
var options: ComponentConstructorOptions<Record<string, any>>;
}
// @filename: index.ts
// @errors: 2554
// ---cut---
const component = new Component(options);
```
A client-side component — that is, a component compiled with `generate: 'dom'` (or the `generate` option left unspecified) is a JavaScript class.
```ts
// @errors: 2554
// @filename: ambient.d.ts
import { SvelteComponent, ComponentConstructorOptions } from 'svelte';
declare module './App.svelte' {
class Component extends SvelteComponent {}
export default Component;
}
// @filename: index.ts
// @errors: 2554
// ---cut---
import App from './App.svelte';
const app = new App({
target: document.body,
props: {
// assuming App.svelte contains something like
// `export let answer`:
answer: 42
}
});
```
The following initialisation options can be provided:
| option | default | description |
| --------- | ----------- | ---------------------------------------------------------------------------------------------------- |
| `target` | **none** | An `HTMLElement` or `ShadowRoot` to render to. This option is required |
| `anchor` | `null` | A child of `target` to render the component immediately before |
| `props` | `{}` | An object of properties to supply to the component |
| `context` | `new Map()` | A `Map` of root-level context key-value pairs to supply to the component |
| `hydrate` | `false` | See below |
| `intro` | `false` | If `true`, will play transitions on initial render, rather than waiting for subsequent state changes |
Existing children of `target` are left where they are.
The `hydrate` option instructs Svelte to upgrade existing DOM (usually from server-side rendering) rather than creating new elements. It will only work if the component was compiled with the [`hydratable: true` option](/docs/svelte-compiler#compile). Hydration of `<head>` elements only works properly if the server-side rendering code was also compiled with `hydratable: true`, which adds a marker to each element in the `<head>` so that the component knows which elements it's responsible for removing during hydration.
Whereas children of `target` are normally left alone, `hydrate: true` will cause any children to be removed. For that reason, the `anchor` option cannot be used alongside `hydrate: true`.
The existing DOM doesn't need to match the component — Svelte will 'repair' the DOM as it goes.
```ts
/// file: index.js
// @filename: ambient.d.ts
import { SvelteComponent, ComponentConstructorOptions } from 'svelte';
declare module './App.svelte' {
class Component extends SvelteComponent {}
export default Component;
}
// @filename: index.ts
// @errors: 2322 2554
// ---cut---
import App from './App.svelte';
const app = new App({
target: document.querySelector('#server-rendered-html'),
hydrate: true
});
```
## `$set`
```ts
// @filename: ambient.d.ts
import { SvelteComponent, ComponentConstructorOptions } from 'svelte';
declare global {
class Component extends SvelteComponent {}
var component: Component;
var props: Record<string, any>;
}
export {};
// @filename: index.ts
// ---cut---
component.$set(props);
```
Programmatically sets props on an instance. `component.$set({ x: 1 })` is equivalent to `x = 1` inside the component's `<script>` block.
Calling this method schedules an update for the next microtask — the DOM is _not_ updated synchronously.
```ts
// @filename: ambient.d.ts
import { SvelteComponent, ComponentConstructorOptions } from 'svelte';
declare global {
class Component extends SvelteComponent {}
var component: Component;
}
export {};
// @filename: index.ts
// ---cut---
component.$set({ answer: 42 });
```
## `$on`
```ts
// @filename: ambient.d.ts
import { SvelteComponent, ComponentConstructorOptions } from 'svelte';
declare global {
class Component extends SvelteComponent {}
var component: Component;
var ev: string;
var callback: (event: CustomEvent) => void;
}
export {};
// @filename: index.ts
// ---cut---
component.$on(ev, callback);
```
Causes the `callback` function to be called whenever the component dispatches an `event`.
A function is returned that will remove the event listener when called.
```ts
/// file: index.js
// @filename: ambient.d.ts
import { SvelteComponent, ComponentConstructorOptions } from 'svelte';
declare global {
class Component extends SvelteComponent {}
var component: Component;
}
export {};
// @filename: index.ts
// ---cut---
const off = component.$on('selected', (event) => {
console.log(event.detail.selection);
});
off();
```
## `$destroy`
```js
// @filename: ambient.d.ts
import { SvelteComponent, ComponentConstructorOptions } from 'svelte';
declare global {
class Component extends SvelteComponent {}
var component: Component;
}
export {}
// @filename: index.ts
// ---cut---
component.$destroy();
```
Removes a component from the DOM and triggers any `onDestroy` handlers.
## Component props
```js
// @filename: ambient.d.ts
import { SvelteComponent, ComponentConstructorOptions } from 'svelte';
declare global {
class Component extends SvelteComponent {}
var component: Component;
}
export {}
// @filename: index.ts
// @errors: 2339
// ---cut---
component.prop;
```
```js
// @filename: ambient.d.ts
import { SvelteComponent, ComponentConstructorOptions } from 'svelte';
declare global {
class Component extends SvelteComponent {}
var component: Component;
var value: unknown;
}
export {}
// @filename: index.ts
// @errors: 2339
// ---cut---
component.prop = value;
```
If a component is compiled with `accessors: true`, each instance will have getters and setters corresponding to each of the component's props. Setting a value will cause a _synchronous_ update, rather than the default async update caused by `component.$set(...)`.
By default, `accessors` is `false`, unless you're compiling as a custom element.
```js
/// file: index.js
// @filename: ambient.d.ts
import { SvelteComponent, ComponentConstructorOptions } from 'svelte';
declare global {
class Component extends SvelteComponent {}
var component: Component;
var props: Record<string, any>;
}
export {}
// @filename: index.ts
// @errors: 2339
// ---cut---
console.log(component.count);
component.count += 1;
```

@ -1,50 +0,0 @@
---
title: 'Server-side component API'
---
```js
// @noErrors
const result = Component.render(...)
```
Unlike client-side components, server-side components don't have a lifespan after you render them — their whole job is to create some HTML and CSS. For that reason, the API is somewhat different.
A server-side component exposes a `render` method that can be called with optional props. It returns an object with `head`, `html`, and `css` properties, where `head` contains the contents of any `<svelte:head>` elements encountered.
You can import a Svelte component directly into Node using [`svelte/register`](/docs/svelte-register).
```js
// @noErrors
require('svelte/register');
const App = require('./App.svelte').default;
const { head, html, css } = App.render({
answer: 42
});
```
The `.render()` method accepts the following parameters:
| parameter | default | description |
| --------- | ------- | -------------------------------------------------- |
| `props` | `{}` | An object of properties to supply to the component |
| `options` | `{}` | An object of options |
The `options` object takes in the following options:
| option | default | description |
| --------- | ----------- | ------------------------------------------------------------------------ |
| `context` | `new Map()` | A `Map` of root-level context key-value pairs to supply to the component |
```js
// @noErrors
const { head, html, css } = App.render(
// props
{ answer: 42 },
// options
{
context: new Map([['context-key', 'context-value']])
}
);
```

@ -1,3 +0,0 @@
{
"title": "Compiler and API"
}

@ -1,16 +1,50 @@
---
title: 'svelte/store'
title: Stores
---
The `svelte/store` module exports functions for creating [readable](/docs/svelte-store#readable), [writable](/docs/svelte-store#writable) and [derived](/docs/svelte-store#derived) stores.
- how to use
- how to write
- TODO should the details for the store methods belong to the reference section?
Keep in mind that you don't _have_ to use these functions to enjoy the [reactive `$store` syntax](/docs/svelte-components#script-4-prefix-stores-with-$-to-access-their-values) in your components. Any object that correctly implements `.subscribe`, unsubscribe, and (optionally) `.set` is a valid store, and will work both with the special syntax, and with Svelte's built-in [`derived` stores](/docs/svelte-store#derived).
A _store_ is an object that allows reactive access to a value via a simple _store contract_. The [`svelte/store` module](/docs/svelte-store) contains minimal store implementations which fulfil this contract.
This makes it possible to wrap almost any other reactive state handling library for use in Svelte. Read more about the [store contract](/docs/svelte-components#script-4-prefix-stores-with-$-to-access-their-values) to see what a correct implementation looks like.
Any time you have a reference to a store, you can access its value inside a component by prefixing it with the `$` character. This causes Svelte to declare the prefixed variable, subscribe to the store at component initialisation and unsubscribe when appropriate.
## `writable`
Assignments to `$`-prefixed variables require that the variable be a writable store, and will result in a call to the store's `.set` method.
> EXPORT_SNIPPET: svelte/store#writable
Note that the store must be declared at the top level of the component — not inside an `if` block or a function, for example.
Local variables (that do not represent store values) must _not_ have a `$` prefix.
```svelte
<script>
import { writable } from 'svelte/store';
const count = writable(0);
console.log($count); // logs 0
count.set(1);
console.log($count); // logs 1
$count = 2;
console.log($count); // logs 2
</script>
```
## When to use stores
Prior to Svelte 5, stores were the go-to solution for creating cross-component reactive states or extracting logic. With runes, these use cases have greatly diminished.
- when extracting logic, it's better to take advantage of runes' universal reactivity: You can use runes outside the top level of components and even place them into JavaScript or TypeScript files (using a `.svelte.js` or `.svelte.ts` file ending)
- when creating shared state, you can create a `$state` object containing the values you need and manipulating said state
Stores are still a good solution when you have complex asynchronous data streams or it's important to have more manual control over updating values or listening to changes. If you're familiar with RxJs and want to reuse that knowledge, the `$` also comes in handy for you.
## svelte/store
The `svelte/store` module contains a minimal store implementation which fulfil the store contract. It provides methods for creating stores that you can update from the outside, stores you can only update from the inside, and for combining and deriving stores.
### `writable`
Function that creates a store which has values that can be set from 'outside' components. It gets created as an object with additional `set` and `update` methods.
@ -55,9 +89,7 @@ unsubscribe(); // logs 'no more subscribers'
Note that the value of a `writable` is lost when it is destroyed, for example when the page is refreshed. However, you can write your own logic to sync the value to for example the `localStorage`.
## `readable`
> EXPORT_SNIPPET: svelte/store#readable
### `readable`
Creates a store whose value cannot be set from 'outside', the first argument is the store's initial value, and the second argument to `readable` is the same as the second argument to `writable`.
@ -83,9 +115,7 @@ const ticktock = readable('tick', (set, update) => {
});
```
## `derived`
> EXPORT_SNIPPET: svelte/store#derived
### `derived`
Derives a store from one or more other stores. The callback runs initially when the first subscriber subscribes and then whenever the store dependencies change.
@ -199,9 +229,7 @@ const delayed = derived([a, b], ([$a, $b], set) => {
});
```
## `readonly`
> EXPORT_SNIPPET: svelte/store#readonly
### `readonly`
This simple helper function makes a store readonly. You can still subscribe to the changes from the original one using this new readable store.
@ -218,9 +246,7 @@ writableStore.set(2); // console: 2
readableStore.set(2); // ERROR
```
## `get`
> EXPORT_SNIPPET: svelte/store#get
### `get`
Generally, you should read the value of a store by subscribing to it and using the value as it changes over time. Occasionally, you may need to retrieve the value of a store to which you're not subscribed. `get` allows you to do so.
@ -243,6 +269,17 @@ import { get } from 'svelte/store';
const value = get(store);
```
## Types
## Store contract
```ts
// @noErrors
store = { subscribe: (subscription: (value: any) => void) => (() => void), set?: (value: any) => void }
```
You can create your own stores without relying on [`svelte/store`](/docs/svelte-store), by implementing the _store contract_:
1. A store must contain a `.subscribe` method, which must accept as its argument a subscription function. This subscription function must be immediately and synchronously called with the store's current value upon calling `.subscribe`. All of a store's active subscription functions must later be synchronously called whenever the store's value changes.
2. The `.subscribe` method must return an unsubscribe function. Calling an unsubscribe function must stop its subscription, and its corresponding subscription function must not be called again by the store.
3. A store may _optionally_ contain a `.set` method, which must accept as its argument a new value for the store, and which synchronously calls all of the store's active subscription functions. Such a store is called a _writable store_.
> TYPES: svelte/store
For interoperability with RxJS Observables, the `.subscribe` method is also allowed to return an object with an `.unsubscribe` method, rather than return the unsubscription function directly. Note however that unless `.subscribe` synchronously calls the subscription (which is not required by the Observable spec), Svelte will see the value of the store as `undefined` until it does.

@ -0,0 +1,131 @@
---
title: Context
---
- get/set/hasContext
- how to use, best practises (like encapsulating them)
Most state is component-level state that lives as long as its component lives. There's also section-wide or app-wide state however, which also needs to be handled somehow.
The easiest way to do that is to create global state and just import that.
```ts
/// file: state.svelte.ts
export const myGlobalState = $state({
user: {
/* ... */
}
/* ... */
});
```
```svelte
<!--- file: App.svelte --->
<script>
import { myGlobalState } from './state.svelte';
// ...
</script>
```
This has a few drawbacks though:
- it only safely works when your global state is only used client-side - for example, when you're building a single page application that does not render any of your components on the server. If your state ends up being managed and updated on the server, it could end up being shared between sessions and/or users, causing bugs
- it may give the false impression that certain state is global when in reality it should only used in a certain part of your app
To solve these drawbacks, Svelte provides a few `context` primitives which alleviate these problems.
## Setting and getting context
To associate an arbitrary object with the current component, use `setContext`.
```svelte
<script>
import { setContext } from 'svelte';
setContext('key', value);
</script>
```
The context is then available to children of the component (including slotted content) with `getContext`.
```svelte
<script>
import { getContext } from 'svelte';
const value = getContext('key');
</script>
```
`setContext` and `getContext` solve the above problems:
- the state is not global, it's scoped to the component. That way it's safe to render your components on the server and not leak state
- it's clear that the state is not global but rather scoped to a specific component tree and therefore can't be used in other parts of your app
> `setContext`/`getContext` must be called during component initialisation.
Context is not inherently reactive. If you need reactive values in context then you can pass a `$state` object into context, whos properties _will_ be reactive.
```svelte
<!--- file: Parent.svelte --->
<script>
import { setContext } from 'svelte';
let value = $state({ count: 0 });
setContext('counter', value);
</script>
<button onclick={() => value.count++}>increment</button>
```
```svelte
<!--- file: Child.svelte --->
<script>
import { setContext } from 'svelte';
const value = setContext('counter');
</script>
<p>Count is {value.count}</p>
```
To check whether a given `key` has been set in the context of a parent component, use `hasContext`.
```svelte
<script>
import { hasContext } from 'svelte';
if (hasContext('key')) {
// do something
}
</script>
```
You can also retrieve the whole context map that belongs to the closest parent component using `getAllContexts`. This is useful, for example, if you programmatically create a component and want to pass the existing context to it.
```svelte
<script>
import { getAllContexts } from 'svelte';
const contexts = getAllContexts();
</script>
```
## Encapsulating context interactions
The above methods are very unopionated about how to use them. When your app grows in scale, it's worthwhile to encapsulate setting and getting the context into functions and properly type them.
```ts
// @errors: 2304
import { getContext, setContext } from 'svelte';
let userKey = Symbol('user');
export function setUserContext(user: User) {
setContext(userKey, user);
}
export function getUserContext(): User {
return getContext(userKey) as User;
}
```

@ -0,0 +1,172 @@
---
title: Lifecycle hooks
---
- onMount/onDestroy
- mention that `$effect` might be better for your use case
- beforeUpdate/afterUpdate with deprecation notice?
- or skip this entirely and only have it in the reference docs?
In Svelte 5, the component lifecycle consists of only two parts: Its creation and its destruction. Everything in-between - when certain state is updated - is not related to the component as a whole, only the parts that need to react to the state change are notified. This is because under the hood the smallest unit of change is actually not a component, it's the (render) effects that the component sets up upon component initialization. Consequently, there's no such thing as a "before update"/"after update" hook.
## `onMount`
The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM. It must be called during the component's initialisation (but doesn't need to live _inside_ the component; it can be called from an external module).
`onMount` does not run inside a component that is rendered on the server.
```svelte
<script>
import { onMount } from 'svelte';
onMount(() => {
console.log('the component has mounted');
});
</script>
```
If a function is returned from `onMount`, it will be called when the component is unmounted.
```svelte
<script>
import { onMount } from 'svelte';
onMount(() => {
const interval = setInterval(() => {
console.log('beep');
}, 1000);
return () => clearInterval(interval);
});
</script>
```
> This behaviour will only work when the function passed to `onMount` _synchronously_ returns a value. `async` functions always return a `Promise`, and as such cannot _synchronously_ return a function.
## `onDestroy`
> EXPORT_SNIPPET: svelte#onDestroy
Schedules a callback to run immediately before the component is unmounted.
Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the only one that runs inside a server-side component.
```svelte
<script>
import { onDestroy } from 'svelte';
onDestroy(() => {
console.log('the component is being destroyed');
});
</script>
```
## `tick`
While there's no "after update" hook, you can use `tick` to ensure that the UI is updated before continuing. `tick` returns a promise that resolves once any pending state changes have been applied, or in the next microtask if there are none.
```svelte
<script>
import { beforeUpdate, tick } from 'svelte';
beforeUpdate(async () => {
console.log('the component is about to update');
await tick();
console.log('the component just updated');
});
</script>
```
## Deprecated: `beforeUpdate` / `afterUpdate`
Svelte 4 contained hooks that ran before and after the component as a whole was updated. For backwards compatibility, these hooks were shimmed in Svelte 5 but not available inside components that use runes.
```svelte
<script>
import { beforeUpdate, afterUpdate } from 'svelte';
beforeUpdate(() => {
console.log('the component is about to update');
});
afterUpdate(() => {
console.log('the component just updated');
});
</script>
```
Instead of `beforeUpdate` use `$effect.pre` and instead of `afterUpdate` use `$effect` instead - these runes offer more granular control and only react to the changes you're actually interested in.
### Chat window example
To implement a chat window that autoscrolls to the bottom when new messages appear (but only if you were _already_ scrolled to the bottom), we need to measure the DOM before we update it.
In Svelte 4, we do this with `beforeUpdate`, but this is a flawed approach — it fires before _every_ update, whether it's relevant or not. In the example below, we need to introduce checks like `updatingMessages` to make sure we don't mess with the scroll position when someone toggles dark mode.
With runes, we can use `$effect.pre`, which behaves the same as `$effect` but runs before the DOM is updated. As long as we explicitly reference `messages` inside the effect body, it will run whenever `messages` changes, but _not_ when `theme` changes.
`beforeUpdate`, and its equally troublesome counterpart `afterUpdate`, are therefore deprecated in Svelte 5.
- [Before](/#H4sIAAAAAAAAE31WXa_bNgz9K6yL1QmWOLlrC-w6H8MeBgwY9tY9NfdBtmlbiywZkpyPBfnvo2zLcZK28AWuRPGI5OGhkEuQc4EmiL9eAskqDOLg97oOZoE9125jDigs0t6oRqfOsjap5rXd7uTO8qpW2sIFEsyVxn_qjFmcAcstar-xPN3DFXKtKgi768IVgQku0ELj3Lgs_kZjWIEGNpAzYXDlHWyJFZI1zJjeh4O5uvl_DY8oUkVeVoFuJKYls-_CGYS25Aboj0EtWNqel0wWoBoLTGZgmdgDS9zW4Uz4NsrswPHoyutN4xInkylstnBxdmIhh8m7xzqmoNE2Wq46n1RJQzEbq4g-JQSl7e-HDx-GdaTy3KD9E3lRWvj5Zu9QX1QN20dj7zyHz8s-1S6lW7Cpz3RnXTcm04hIlfdFuO8p2mQ5-3a06cqjrn559bF_2NHOnRZ5I1PLlXQNyQT-hedMHeUEDyjtdMxsa4n2eIbNhlTwhyRthaOKOmYtniwF6pwt0wXa6MBEg0OibZec27gz_dk3UrZ6hB2LLYoiv521Yd8Gt-foTrfhiCDP0lC9VUUhcDLU49Xe_9943cNvEArHfAjxeBTovvXiNpFynfEDpIIZs9kFbg52QbeNHWZzebz32s7xHco3nJAJl1nshmhz8dYOQJDyZetnbb2gTWe-vEeWlrfpZMavr56ldb29eNt6UXvgwgFbp_WC0tl2RK25rGk6lYz3nUI2lzvBXGHhPZPGWmKUXFNBKqdaW259wl_aHbiqoVIZdpE60Nax6IOujT0LbFFxIVTCxCRR2XloUcYNvSbnGHKBp763jHoj59xiZWJI0Wm0P_m3MSS985xkasn-cFq20xTDy3J5KFcjgUTD69BHdcHIjz431z28IqlxGcPSfdFnrGDZn6gD6lyo45zyHAD-btczf-98nhQxHEvKfeUtOVkSejD3q-9X7JbzjGtsdUxlKdFU8qGsT78uaw848syWMXz85Waq2Gnem4mAn3prweq4q6Y3JEpnqMmnPoFRgmd3ySW0LLRqSKlwYHriCvJvUs2yjMaaoA-XzTXLeGMe45zmhv_XAno3Mj0xF7USuqNvnE9H343QHlq-eAgxpbTPNR9yzUkgLjwSR0NK4wKoxy-jDg-9vy8sUSToakzW-9fX13Em9Q8T6Z26uZhBN36XUYo5q7ggLXBZoub2Ofv7g6GCZfTxe034NCjiudXj7Omla0eTfo7QBPOcYxbE7qG-vl3_B1G-_i_JCAAA)
- [After](/#H4sIAAAAAAAAE31WXa-jNhD9K7PsdknUQJLurtRLPqo-VKrU1327uQ8GBnBjbGSb5KZR_nvHgMlXtyIS9njO-MyZGZRzUHCBJkhez4FkNQZJ8HvTBLPAnhq3MQcUFmlvVKszZ1mbTPPGbndyZ3ndKG3hDJZne7hAoVUNYY8JV-RBPgIt2AprhA18MpZZnIQ50_twuvLHNRrDSjRXj9fwiCJTBLIKdCsxq5j9EM4gtBU3QD8GjWBZd14xWYJqLTCZg2ViDyx1W4cz4dv0hsiB49FRHkyfsCgws3GjcTKZwmYLZ2feWc9o1W8zJQ2Fb62i5JUQRNRHgs-fx3WsisKg_RN5WVn4-WrvUd9VA9tH4-AcwbfFQIpkLWByvWzqSe2sk3kyjUlOec_XPU-3TRaz_75tuvKoi19e3OvipSpamVmupJM2F_gXnnJ1lBM8oLQjHceys8R7PMFms4HwD2lRhzeEe-EsvluSrHe2TJdo4wMTLY48XKwPzm0KGm2r5ajFtRYU4TWOY7-ddWHfxhDP0QkQhnf5PWRnVVkKnIx8fZsOb5dR16nwG4TCCRdCMphWQ7z1_DoOcp3zA2SCGbPZBa5jd0G_TRxmc36Me-mG6A7l60XIlMs8ce2-OXtrDyBItdz6qVjPadObzx-RZdV1nJjx64tXad1sz962njceOHfAzmk9JzrbXqg1lw3NkZL7vgE257t-uMDcO6attSSokpmgFqVMO2U93e_dDlzOUKsc-3t6zNZp6K9cG3sS2KGSUqiUiUmq8tNYoJwbmvpTAoXA96GyjCojI26xNglk6DpwOPm7NdRYp4ia0JL94bTqRiGB5WJxqFY37RGPoz3c6i4jP3rcUA7wmhqNywQW7om_YQ2L4UQdUBdCHSPiOQJ8bFcxHzeK0jKBY0XcV95SkCWlD9t-9eOM3TLKucauiyktJdpaPqT19ddF4wFHntsqgS-_XE01e48GMwnw02AtWZP02QyGVOkcNfk072CU4PkduZSWpVYt9SkcmJ64hPwHpWF5ziVls3wIFmmW89Y83vMeGf5PBxjcyPSkXNy10J18t3x6-a6CDtBq6SGklNKeazFyLahB3PVIGo2UbhOgGi9vKjzW_j6xVFFD17difXx5ebll0vwvkcGpn4sZ9MN3vqFYsJoL6gUuK9TcPrO_PxgzWMRfflSEr2NHPJf6lj1957rRpH8CNMG84JgHidUtXt4u_wK21LXERAgAAA==)
```diff
<script>
- import { beforeUpdate, afterUpdate, tick } from 'svelte';
+ import { tick } from 'svelte';
- let updatingMessages = false;
- let theme = 'dark';
- let messages = [];
+ let theme = $state('dark');
+ let messages = $state([]);
let viewport;
- beforeUpdate(() => {
+ $effect.pre(() => {
- if (!updatingMessages) return;
+ messages;
const autoscroll = viewport && viewport.offsetHeight + viewport.scrollTop > viewport.scrollHeight - 50;
if (autoscroll) {
tick().then(() => {
viewport.scrollTo(0, viewport.scrollHeight);
});
}
- updatingMessages = false;
});
function handleKeydown(event) {
if (event.key === 'Enter') {
const text = event.target.value;
if (!text) return;
- updatingMessages = true;
messages = [...messages, text];
event.target.value = '';
}
}
function toggle() {
toggleValue = !toggleValue;
}
</script>
<div class:dark={theme === 'dark'}>
<div bind:this={viewport}>
{#each messages as message}
<p>{message}</p>
{/each}
</div>
- <input on:keydown={handleKeydown} />
+ <input onkeydown={handleKeydown} />
- <button on:click={toggle}>
+ <button onclick={toggle}>
Toggle dark mode
</button>
</div>
```

@ -0,0 +1,76 @@
---
title: Imperative component API
---
better title needed?
- mount
- unmount
- render
- hydrate
- how they interact with each other
Every Svelte application starts by imperatively creating a root component. On the client this component is mounted to a specific element. On the server, you want to get back a string of HTML instead which you can render. The following functions help you achieve those tasks.
## `mount`
Instantiates a component and mounts it to the given target:
```js
// @errors: 2322
import { mount } from 'svelte';
import App from './App.svelte';
const app = mount(App, {
target: document.querySelector('#app'),
props: { some: 'property' }
});
```
You can mount multiple components per page, and you can also mount from within your application, for example when creating a tooltip component and attaching it to the hovered element.
## `unmount`
Unmounts a component created with [`mount`](#mount) or [`hydrate`](#hydrate):
```js
// @errors: 1109
import { mount, unmount } from 'svelte';
import App from './App.svelte';
const app = mount(App, {...});
// later
unmount(app);
```
## `render`
Only available on the server and when compiling with the `server` option. Takes a component and returns an object with `body` and `head` properties on it, which you can use to populate the HTML when server-rendering your app:
```js
// @errors: 2724 2305 2307
import { render } from 'svelte/server';
import App from './App.svelte';
const result = render(App, {
props: { some: 'property' }
});
result.body; // HTML for somewhere in this <body> tag
result.head; // HTML for somewhere in this <head> tag
```
## `hydrate`
Like `mount`, but will reuse up any HTML rendered by Svelte's SSR output (from the [`render`](#server-render) function) inside the target and make it interactive:
```js
// @errors: 2322
import { hydrate } from 'svelte';
import App from './App.svelte';
const app = hydrate(App, {
target: document.querySelector('#app'),
props: { some: 'property' }
});
```

@ -0,0 +1,3 @@
---
title: Runtime
---

@ -0,0 +1,94 @@
---
title: Debugging
---
- `@debug`
- `$inspect`
Svelte provides two built-in ways to debug your application.
## `$inspect`
The `$inspect` rune is roughly equivalent to `console.log`, with the exception that it will re-run whenever its
argument changes. `$inspect` tracks reactive state deeply, meaning that updating something inside an object
or array using fine-grained reactivity will cause it to re-fire. ([Demo:](/#H4sIAAAAAAAACkWQ0YqDQAxFfyUMhSotdZ-tCvu431AXtGOqQ2NmmMm0LOK_r7Utfby5JzeXTOpiCIPKT5PidkSVq2_n1F7Jn3uIcEMSXHSw0evHpAjaGydVzbUQCmgbWaCETZBWMPlKj29nxBDaHj_edkAiu12JhdkYDg61JGvE_s2nR8gyuBuiJZuDJTyQ7eE-IEOzog1YD80Lb0APLfdYc5F9qnFxjiKWwbImo6_llKRQVs-2u91c_bD2OCJLkT3JZasw7KLA2XCX31qKWE6vIzNk1fKE0XbmYrBTufiI8-_8D2cUWBA_AQAA))
```svelte
<script>
let count = $state(0);
let message = $state('hello');
$inspect(count, message); // will console.log when `count` or `message` change
</script>
<button onclick={() => count++}>Increment</button>
<input bind:value={message} />
```
`$inspect` returns a property `with`, which you can invoke with a callback, which will then be invoked instead of `console.log`. The first argument to the callback is either `"init"` or `"update"`, all following arguments are the values passed to `$inspect`. [Demo:](/#H4sIAAAAAAAACkVQ24qDMBD9lSEUqlTqPlsj7ON-w7pQG8c2VCchmVSK-O-bKMs-DefKYRYx6BG9qL4XQd2EohKf1opC8Nsm4F84MkbsTXAqMbVXTltuWmp5RAZlAjFIOHjuGLOP_BKVqB00eYuKs82Qn2fNjyxLtcWeyUE2sCRry3qATQIpJRyD7WPVMf9TW-7xFu53dBcoSzAOrsqQNyOe2XUKr0Xi5kcMvdDB2wSYO-I9vKazplV1-T-d6ltgNgSG1KjVUy7ZtmdbdjqtzRcphxMS1-XubOITJtPrQWMvKnYB15_1F7KKadA_AQAA)
```svelte
<script>
let count = $state(0);
$inspect(count).with((type, count) => {
if (type === 'update') {
debugger; // or `console.trace`, or whatever you want
}
});
</script>
<button onclick={() => count++}>Increment</button>
```
A convenient way to find the origin of some change is to pass `console.trace` to `with`:
```js
// @errors: 2304
$inspect(stuff).with(console.trace);
```
> `$inspect` only works during development. In a production build it becomes a noop.
## @debug
```svelte
<!--- copy: false --->
{@debug}
```
```svelte
<!--- copy: false --->
{@debug var1, var2, ..., varN}
```
The `{@debug ...}` tag offers an alternative to `console.log(...)`. It logs the values of specific variables whenever they change, and pauses code execution if you have devtools open.
```svelte
<script>
let user = {
firstname: 'Ada',
lastname: 'Lovelace'
};
</script>
{@debug user}
<h1>Hello {user.firstname}!</h1>
```
`{@debug ...}` accepts a comma-separated list of variable names (not arbitrary expressions).
```svelte
<!-- Compiles -->
{@debug user}
{@debug user1, user2, user3}
<!-- WON'T compile -->
{@debug user.firstname}
{@debug myArray[0]}
{@debug !isReady}
{@debug typeof user === 'object'}
```
The `{@debug}` tag without any arguments will insert a `debugger` statement that gets triggered when _any_ state changes, as opposed to the specified variables.

@ -1,126 +0,0 @@
---
title: Frequently asked questions
---
## I'm new to Svelte. Where should I start?
We think the best way to get started is playing through the interactive [tutorial](https://learn.svelte.dev/). Each step there is mainly focused on one specific aspect and is easy to follow. You'll be editing and running real Svelte components right in your browser.
Five to ten minutes should be enough to get you up and running. An hour and a half should get you through the entire tutorial.
## Where can I get support?
If your question is about certain syntax, the [API page](https://svelte.dev/docs) is a good place to start.
Stack Overflow is a popular forum to ask code-level questions or if youre stuck with a specific error. Read through the existing questions tagged with [Svelte](https://stackoverflow.com/questions/tagged/svelte+or+svelte-3) or [ask your own](https://stackoverflow.com/questions/ask?tags=svelte)!
There are online forums and chats which are a great place for discussion about best practices, application architecture or just to get to know fellow Svelte users. [Our Discord](https://svelte.dev/chat) or [the Reddit channel](https://www.reddit.com/r/sveltejs/) are examples of that. If you have an answerable code-level question, Stack Overflow is usually a better fit.
## Are there any third-party resources?
Svelte Society maintains a [list of books and videos](https://sveltesociety.dev/resources).
## How can I get VS Code to syntax-highlight my .svelte files?
There is an [official VS Code extension for Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode).
## Is there a tool to automatically format my .svelte files?
You can use prettier with the [prettier-plugin-svelte](https://www.npmjs.com/package/prettier-plugin-svelte) plugin.
## How do I document my components?
In editors which use the Svelte Language Server you can document Components, functions and exports using specially formatted comments.
````svelte
<script>
/** What should we call the user? */
export let name = 'world';
</script>
<!--
@component
Here's some documentation for this component.
It will show up on hover.
- You can use markdown here.
- You can also use code blocks here.
- Usage:
```tsx
<main name="Arethra">
```
-->
<main>
<h1>
Hello, {name}
</h1>
</main>
````
Note: The `@component` is necessary in the HTML comment which describes your component.
## Does Svelte scale?
There will be a blog post about this eventually, but in the meantime, check out [this issue](https://github.com/sveltejs/svelte/issues/2546).
## Is there a UI component library?
There are several UI component libraries as well as standalone components. Find them under the [design systems section of the components page](https://sveltesociety.dev/components#design-systems) on the Svelte Society website.
## How do I test Svelte apps?
How your application is structured and where logic is defined will determine the best way to ensure it is properly tested. It is important to note that not all logic belongs within a component - this includes concerns such as data transformation, cross-component state management, and logging, among others. Remember that the Svelte library has its own test suite, so you do not need to write tests to validate implementation details provided by Svelte.
A Svelte application will typically have three different types of tests: Unit, Component, and End-to-End (E2E).
_Unit Tests_: Focus on testing business logic in isolation. Often this is validating individual functions and edge cases. By minimizing the surface area of these tests they can be kept lean and fast, and by extracting as much logic as possible from your Svelte components more of your application can be covered using them. When creating a new SvelteKit project, you will be asked whether you would like to setup [Vitest](https://vitest.dev/) for unit testing. There are a number of other test runners that could be used as well.
_Component Tests_: Validating that a Svelte component mounts and interacts as expected throughout its lifecycle requires a tool that provides a Document Object Model (DOM). Components can be compiled (since Svelte is a compiler and not a normal library) and mounted to allow asserting against element structure, listeners, state, and all the other capabilities provided by a Svelte component. Tools for component testing range from an in-memory implementation like jsdom paired with a test runner like [Vitest](https://vitest.dev/) to solutions that leverage an actual browser to provide a visual testing capability such as [Playwright](https://playwright.dev/docs/test-components) or [Cypress](https://www.cypress.io/).
_End-to-End Tests_: To ensure your users are able to interact with your application it is necessary to test it as a whole in a manner as close to production as possible. This is done by writing end-to-end (E2E) tests which load and interact with a deployed version of your application in order to simulate how the user will interact with your application. When creating a new SvelteKit project, you will be asked whether you would like to setup [Playwright](https://playwright.dev/) for end-to-end testing. There are many other E2E test libraries available for use as well.
Some resources for getting started with testing:
- [Svelte Testing Library](https://testing-library.com/docs/svelte-testing-library/example/)
- [Svelte Component Testing in Cypress](https://docs.cypress.io/guides/component-testing/svelte/overview)
- [Example using vitest](https://github.com/vitest-dev/vitest/tree/main/examples/svelte)
- [Example using uvu test runner with JSDOM](https://github.com/lukeed/uvu/tree/master/examples/svelte)
- [Test Svelte components using Vitest & Playwright](https://davipon.hashnode.dev/test-svelte-component-using-vitest-playwright)
- [Component testing with WebdriverIO](https://webdriver.io/docs/component-testing/svelte)
## Is there a router?
The official routing library is [SvelteKit](https://kit.svelte.dev/). SvelteKit provides a filesystem router, server-side rendering (SSR), and hot module reloading (HMR) in one easy-to-use package. It shares similarities with Next.js for React.
However, you can use any router library. Some framework-agnostic libraries include [navaid](https://github.com/lukeed/navaid); [universal-router](https://github.com/kriasoft/universal-router), which is isomorphic; [Hono](https://hono.dev/), which supports multiple JS runtimes; and [TanStack Router](https://github.com/TanStack/router/tree/beta-agnostic), which is typesafe and supports caching.
If you prefer a declarative HTML approach, the isomorphic [svelte-routing](https://github.com/EmilTholin/svelte-routing) and [svelte-pilot](https://svelte-pilot.github.io/en/link#toc) libraries are available.
If you need hash-based routing on the client side, check out [svelte-spa-router](https://github.com/ItalyPaleAle/svelte-spa-router) or [abstract-state-router](https://github.com/TehShrike/abstract-state-router/).
[Routify](https://routify.dev) is another filesystem-based router, similar to SvelteKit's router. Version 3 supports Svelte's native SSR.
[Vike](https://vike.dev/svelte) is another Vite-based router, like SvelteKit's router, but is still experimental.
You can see a [community-maintained list of routers on sveltesociety.dev](https://sveltesociety.dev/components#routers).
## Can I tell Svelte not to remove my unused styles?
No. Svelte removes the styles from the component and warns you about them in order to prevent issues that would otherwise arise.
Svelte's component style scoping works by generating a class unique to the given component, adding it to the relevant elements in the component that are under Svelte's control, and then adding it to each of the selectors in that component's styles. When the compiler can't see what elements a style selector applies to, there would be two bad options for keeping it:
- If it keeps the selector and adds the scoping class to it, the selector will likely not match the expected elements in the component, and they definitely won't if they were created by a child component or `{@html ...}`.
- If it keeps the selector without adding the scoping class to it, the given style will become a global style, affecting your entire page.
If you need to style something that Svelte can't identify at compile time, you will need to explicitly opt into global styles by using `:global(...)`. But also keep in mind that you can wrap `:global(...)` around only part of a selector. `.foo :global(.bar) { ... }` will style any `.bar` elements that appear within the component's `.foo` elements. As long as there's some parent element in the current component to start from, partially global selectors like this will almost always be able to get you what you want.
## Is Svelte v2 still available?
New features aren't being added to it, and bugs will probably only be fixed if they are extremely nasty or present some sort of security vulnerability.
The documentation is still available [here](https://v2.svelte.dev/guide).
## How do I do hot module reloading?
We recommend using [SvelteKit](https://kit.svelte.dev/), which supports HMR out of the box and is built on top of [Vite](https://vitejs.dev/) and [svelte-hmr](https://github.com/sveltejs/svelte-hmr). There are also community plugins for [rollup](https://github.com/rixo/rollup-plugin-svelte-hot) and [webpack](https://github.com/sveltejs/svelte-loader).

@ -1,360 +0,0 @@
---
title: 'Accessibility warnings'
---
Accessibility (shortened to a11y) isn't always easy to get right, but Svelte will help by warning you at compile time if you write inaccessible markup. However, keep in mind that many accessibility issues can only be identified at runtime using other automated tools and by manually testing your application.
Some warnings may be incorrect in your concrete use case. You can disable such false positives by placing a `<!-- svelte-ignore a11y-<code> -->` comment above the line that causes the warning. Example:
```svelte
<!-- svelte-ignore a11y-autofocus -->
<input autofocus />
```
Here is a list of accessibility checks Svelte will do for you.
## `a11y-accesskey`
Enforce no `accesskey` on element. Access keys are HTML attributes that allow web developers to assign keyboard shortcuts to elements. Inconsistencies between keyboard shortcuts and keyboard commands used by screen reader and keyboard-only users create accessibility complications. To avoid complications, access keys should not be used.
<!-- prettier-ignore -->
```svelte
<!-- A11y: Avoid using accesskey -->
<div accessKey="z" />
```
## `a11y-aria-activedescendant-has-tabindex`
An element with `aria-activedescendant` must be tabbable, so it must either have an inherent `tabindex` or declare `tabindex` as an attribute.
```svelte
<!-- A11y: Elements with attribute aria-activedescendant should have tabindex value -->
<div aria-activedescendant="some-id" />
```
## `a11y-aria-attributes`
Certain reserved DOM elements do not support ARIA roles, states and properties. This is often because they are not visible, for example `meta`, `html`, `script`, `style`. This rule enforces that these DOM elements do not contain the `aria-*` props.
```svelte
<!-- A11y: <meta> should not have aria-* attributes -->
<meta aria-hidden="false" />
```
## `a11y-autofocus`
Enforce that `autofocus` is not used on elements. Autofocusing elements can cause usability issues for sighted and non-sighted users alike.
```svelte
<!-- A11y: Avoid using autofocus -->
<input autofocus />
```
## `a11y-click-events-have-key-events`
Enforce that visible, non-interactive elements with an `on:click` event are accompanied by a keyboard event handler.
Users should first consider whether an interactive element might be more appropriate such as a `<button type="button">` element for actions or `<a>` element for navigations. These elements are more semantically meaningful and will have built-in key handling. E.g. `Space` and `Enter` will trigger a `<button>` and `Enter` will trigger an `<a>` element.
If a non-interactive element is required then `on:click` should be accompanied by an `on:keyup` or `on:keydown` handler that enables the user to perform equivalent actions via the keyboard. In order for the user to be able to trigger a key press, the element will also need to be focusable by adding a [`tabindex`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex). While an `on:keypress` handler will also silence this warning, it should be noted that the `keypress` event is deprecated.
```svelte
<!-- A11y: visible, non-interactive elements with an on:click event must be accompanied by a keyboard event handler. -->
<div on:click={() => {}} />
```
Coding for the keyboard is important for users with physical disabilities who cannot use a mouse, AT compatibility, and screenreader users.
## `a11y-distracting-elements`
Enforces that no distracting elements are used. Elements that can be visually distracting can cause accessibility issues with visually impaired users. Such elements are most likely deprecated, and should be avoided.
The following elements are visually distracting: `<marquee>` and `<blink>`.
```svelte
<!-- A11y: Avoid <marquee> elements -->
<marquee />
```
## `a11y-hidden`
Certain DOM elements are useful for screen reader navigation and should not be hidden.
<!-- prettier-ignore -->
```svelte
<!-- A11y: <h2> element should not be hidden -->
<h2 aria-hidden="true">invisible header</h2>
```
## `a11y-img-redundant-alt`
Enforce img alt attribute does not contain the word image, picture, or photo. Screen readers already announce `img` elements as an image. There is no need to use words such as _image_, _photo_, and/or _picture_.
```svelte
<img src="foo" alt="Foo eating a sandwich." />
<!-- aria-hidden, won't be announced by screen reader -->
<img src="bar" aria-hidden="true" alt="Picture of me taking a photo of an image" />
<!-- A11y: Screen readers already announce <img> elements as an image. -->
<img src="foo" alt="Photo of foo being weird." />
<!-- A11y: Screen readers already announce <img> elements as an image. -->
<img src="bar" alt="Image of me at a bar!" />
<!-- A11y: Screen readers already announce <img> elements as an image. -->
<img src="foo" alt="Picture of baz fixing a bug." />
```
## `a11y-incorrect-aria-attribute-type`
Enforce that only the correct type of value is used for aria attributes. For example, `aria-hidden`
should only receive a boolean.
```svelte
<!-- A11y: The value of 'aria-hidden' must be exactly one of true or false -->
<div aria-hidden="yes" />
```
## `a11y-invalid-attribute`
Enforce that attributes important for accessibility have a valid value. For example, `href` should not be empty, `'#'`, or `javascript:`.
```svelte
<!-- A11y: '' is not a valid href attribute -->
<a href="">invalid</a>
```
## `a11y-interactive-supports-focus`
Enforce that elements with an interactive role and interactive handlers (mouse or key press) must be focusable or tabbable.
```svelte
<!-- A11y: Elements with the 'button' interactive role must have a tabindex value. -->
<div role="button" on:keypress={() => {}} />
```
## `a11y-label-has-associated-control`
Enforce that a label tag has a text label and an associated control.
There are two supported ways to associate a label with a control:
- Wrapping a control in a label tag.
- Adding `for` to a label and assigning it the ID of an input on the page.
```svelte
<label for="id">B</label>
<label>C <input type="text" /></label>
<!-- A11y: A form label must be associated with a control. -->
<label>A</label>
```
## `a11y-media-has-caption`
Providing captions for media is essential for deaf users to follow along. Captions should be a transcription or translation of the dialogue, sound effects, relevant musical cues, and other relevant audio information. Not only is this important for accessibility, but can also be useful for all users in the case that the media is unavailable (similar to `alt` text on an image when an image is unable to load).
The captions should contain all important and relevant information to understand the corresponding media. This may mean that the captions are not a 1:1 mapping of the dialogue in the media content. However, captions are not necessary for video components with the `muted` attribute.
```svelte
<video><track kind="captions" /></video>
<audio muted />
<!-- A11y: Media elements must have a <track kind=\"captions\"> -->
<video />
<!-- A11y: Media elements must have a <track kind=\"captions\"> -->
<video><track /></video>
```
## `a11y-misplaced-role`
Certain reserved DOM elements do not support ARIA roles, states and properties. This is often because they are not visible, for example `meta`, `html`, `script`, `style`. This rule enforces that these DOM elements do not contain the `role` props.
```svelte
<!-- A11y: <meta> should not have role attribute -->
<meta role="tooltip" />
```
## `a11y-misplaced-scope`
The scope attribute should only be used on `<th>` elements.
<!-- prettier-ignore -->
```svelte
<!-- A11y: The scope attribute should only be used with <th> elements -->
<div scope="row" />
```
## `a11y-missing-attribute`
Enforce that attributes required for accessibility are present on an element. This includes the following checks:
- `<a>` should have an href (unless it's a [fragment-defining tag](https://github.com/sveltejs/svelte/issues/4697))
- `<area>` should have alt, aria-label, or aria-labelledby
- `<html>` should have lang
- `<iframe>` should have title
- `<img>` should have alt
- `<object>` should have title, aria-label, or aria-labelledby
- `<input type="image">` should have alt, aria-label, or aria-labelledby
```svelte
<!-- A11y: <input type=\"image\"> element should have an alt, aria-label or aria-labelledby attribute -->
<input type="image" />
<!-- A11y: <html> element should have a lang attribute -->
<html />
<!-- A11y: <a> element should have an href attribute -->
<a>text</a>
```
## `a11y-missing-content`
Enforce that heading elements (`h1`, `h2`, etc.) and anchors have content and that the content is accessible to screen readers
```svelte
<!-- A11y: <a> element should have child content -->
<a href="/foo" />
<!-- A11y: <h1> element should have child content -->
<h1 />
```
## `a11y-mouse-events-have-key-events`
Enforce that `on:mouseover` and `on:mouseout` are accompanied by `on:focus` and `on:blur`, respectively. This helps to ensure that any functionality triggered by these mouse events is also accessible to keyboard users.
```svelte
<!-- A11y: on:mouseover must be accompanied by on:focus -->
<div on:mouseover={handleMouseover} />
<!-- A11y: on:mouseout must be accompanied by on:blur -->
<div on:mouseout={handleMouseout} />
```
## `a11y-no-redundant-roles`
Some HTML elements have default ARIA roles. Giving these elements an ARIA role that is already set by the browser [has no effect](https://www.w3.org/TR/using-aria/#aria-does-nothing) and is redundant.
```svelte
<!-- A11y: Redundant role 'button' -->
<button role="button" />
<!-- A11y: Redundant role 'img' -->
<img role="img" src="foo.jpg" />
```
## `a11y-no-interactive-element-to-noninteractive-role`
[WAI-ARIA](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) roles should not be used to convert an interactive element to a non-interactive element. Non-interactive ARIA roles include `article`, `banner`, `complementary`, `img`, `listitem`, `main`, `region` and `tooltip`.
```svelte
<!-- A11y: <textarea> cannot have role 'listitem' -->
<textarea role="listitem" />
```
### `a11y-no-noninteractive-element-interactions`
A non-interactive element does not support event handlers (mouse and key handlers). Non-interactive elements include `<main>`, `<area>`, `<h1>` (,`<h2>`, etc), `<p>`, `<img>`, `<li>`, `<ul>` and `<ol>`. Non-interactive [WAI-ARIA roles](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) include `article`, `banner`, `complementary`, `img`, `listitem`, `main`, `region` and `tooltip`.
```sv
<!-- `A11y: Non-interactive element <li> should not be assigned mouse or keyboard event listeners.` -->
<li on:click={() => {}} />
<!-- `A11y: Non-interactive element <div> should not be assigned mouse or keyboard event listeners.` -->
<div role="listitem" on:click={() => {}} />
```
### `a11y-no-noninteractive-element-to-interactive-role`
[WAI-ARIA](https://www.w3.org/TR/wai-aria-1.1/#usage_intro) roles should not be used to convert a non-interactive element to an interactive element. Interactive ARIA roles include `button`, `link`, `checkbox`, `menuitem`, `menuitemcheckbox`, `menuitemradio`, `option`, `radio`, `searchbox`, `switch` and `textbox`.
```svelte
<!-- A11y: Non-interactive element <h3> cannot have interactive role 'searchbox' -->
<h3 role="searchbox">Button</h3>
```
## `a11y-no-noninteractive-tabindex`
Tab key navigation should be limited to elements on the page that can be interacted with.
<!-- prettier-ignore -->
```svelte
<!-- A11y: noninteractive element cannot have nonnegative tabIndex value -->
<div tabindex="0" />
```
## a11y-no-static-element-interactions
Elements like `<div>` with interactive handlers like `click` must have an ARIA role.
<!-- prettier-ignore -->
```svelte
<!-- A11y: <div> with click handler must have an ARIA role -->
<div on:click={() => ''} />
```
## `a11y-positive-tabindex`
Avoid positive `tabindex` property values. This will move elements out of the expected tab order, creating a confusing experience for keyboard users.
<!-- prettier-ignore -->
```svelte
<!-- A11y: avoid tabindex values above zero -->
<div tabindex="1" />
```
## `a11y-role-has-required-aria-props`
Elements with ARIA roles must have all required attributes for that role.
```svelte
<!-- A11y: A11y: Elements with the ARIA role "checkbox" must have the following attributes defined: "aria-checked" -->
<span role="checkbox" aria-labelledby="foo" tabindex="0" />
```
## `a11y-role-supports-aria-props`
Elements with explicit or implicit roles defined contain only `aria-*` properties supported by that role.
```svelte
<!-- A11y: The attribute 'aria-multiline' is not supported by the role 'link'. -->
<div role="link" aria-multiline />
<!-- A11y: The attribute 'aria-required' is not supported by the role 'listitem'. This role is implicit on the element <li>. -->
<li aria-required />
```
## `a11y-structure`
Enforce that certain DOM elements have the correct structure.
```svelte
<!-- A11y: <figcaption> must be an immediate child of <figure> -->
<div>
<figcaption>Image caption</figcaption>
</div>
```
## `a11y-unknown-aria-attribute`
Enforce that only known ARIA attributes are used. This is based on the [WAI-ARIA States and Properties spec](https://www.w3.org/WAI/PF/aria-1.1/states_and_properties).
```svelte
<!-- A11y: Unknown aria attribute 'aria-labeledby' (did you mean 'labelledby'?) -->
<input type="image" aria-labeledby="foo" />
```
## `a11y-unknown-role`
Elements with ARIA roles must use a valid, non-abstract ARIA role. A reference to role definitions can be found at [WAI-ARIA](https://www.w3.org/TR/wai-aria/#role_definitions) site.
<!-- prettier-ignore -->
```svelte
<!-- A11y: Unknown role 'toooltip' (did you mean 'tooltip'?) -->
<div role="toooltip" />
```

@ -0,0 +1,8 @@
---
title: Testing
---
- component testing basics
- rune testing basics
- vitest setup
- e2e

@ -2,11 +2,43 @@
title: TypeScript
---
- [basically what we have today](https://svelte.dev/docs/typescript)
- built-in support, but only for type-only features
- generics
- using `Component` and the other helper types
- using `svelte-check`
You can use TypeScript within Svelte components. IDE extensions like the [Svelte VSCode extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) will help you catch errors right in your editor, and [`svelte-check`](https://www.npmjs.com/package/svelte-check) does the same on the command line, which you can integrate into your CI.
## Setup
## `<script lang="ts">`
To use TypeScript within Svelte components, you need to add a preprocessor that will turn TypeScript into JavaScript.
To use TypeScript inside your Svelte components, add `lang="ts"` to your `script` tags:
```svelte
<script lang="ts">
let name: string = 'world';
function greet(name: string) {
alert(`Hello, ${name}!`);
}
</script>
<button onclick={(e: Event) => greet(e.target.innerText)}>
{name as string}
</button>
```
Doing so allows you to use TypeScript's _type-only_ features. That is, all features that just disappear when transpiling to JavaScript, such as type annotations or interface declarations. Features that require the TypeScript compiler to output actual code are not supported. This includes:
- using enums
- using `private`, `protected` or `public` modifiers in constructor functions together with initializers
- using features that are not yet part of the ECMAScript standard (i.e. not level 4 in the TC39 process) and therefore not implemented yet within Acorn, the parser we use for parsing JavaScript
If you want to use one of these features, you need to setup up a `script` preprocessor.
## Preprocessor setup
To use non-type-only TypeScript features within Svelte components, you need to add a preprocessor that will turn TypeScript into JavaScript.
### Using SvelteKit or Vite
@ -45,79 +77,127 @@ If you're using tools like Rollup or Webpack instead, install their respective S
> If you're starting a new project, we recommend using SvelteKit or Vite instead
## `<script lang="ts">`
## Typing `$props`
To use TypeScript inside your Svelte components, add `lang="ts"` to your `script` tags:
Type `$props` just like a regular object with certain properties.
```svelte
<script lang="ts">
let name: string = 'world';
function greet(name: string) {
alert(`Hello, ${name}!`);
import type { Snippet } from 'svelte';
interface Props {
requiredProperty: number;
optionalProperty?: boolean;
snippetWithStringArgument: Snippet<[string]>;
eventHandler: (arg: string) => void;
[key: string]: unknown;
}
let {
requiredProperty,
optionalProperty,
snippetWithStringArgument,
eventHandler,
...everythingElse
}: Props = $props();
</script>
<button onclick={() => eventHandler('clicked button')}>
{@render snippetWithStringArgument('hello')}
</button>
```
### Props
## Generic `$props`
Props can be typed directly on the `export let` statement:
Components can declare a generic relationship between their properties. One example is a generic list component that receives a list of items and a callback property that reveives an item from the list. To declare that the `items` property and the `select` callback operate on the same types, add the `generics` attribute to the `script` tag:
```svelte
<script lang="ts">
export let name: string;
<script lang="ts" generics="Item extends { text: string }">
interface Props {
items: Item[];
select: Item;
}
let { items, select } = $props();
</script>
{#each items as item}
<button onclick={() => select(item)}>
{item.text}
</button>
{/each}
```
### Slots
The content of `generics` is what you would put between the `<...>` tags of a generic function. In other words, you can use multiple generics, `extends` and fallback types.
Slot and slot prop types are inferred from the types of the slot props passed to them:
## Typing `$state`
```svelte
<script lang="ts">
export let name: string;
</script>
You can type `$state` like any other variable.
```ts
let count: number = $state(0);
```
<slot {name} />
If you don't give `$state` an initial value, part of its types will be `undefined`.
<!-- Later -->
<Comp let:name>
<!-- ^ Inferred as string -->
{name}
</Comp>
```ts
// @noErrors
// Error: Type 'number | undefined' is not assignable to type 'number'
let count: number = $state();
```
### Events
If you know that the variable _will_ be defined before you first use it, use an `as` casting. This is especially useful in the context of classes:
Events can be typed with `createEventDispatcher`:
```ts
class Counter {
count = $state() as number;
constructor(initial: number) {
this.count = initial;
}
}
```
## The `Component` type
Svelte components or of type `Component`. You can use it and its related types to express a variety of constraints.
Using it together with `<svelte:component>` to restrict what kinds of component can be passed to it:
```svelte
<script lang="ts">
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher<{
event: null; // does not accept a payload
click: string; // has a required string payload
type: string | null; // has an optional string payload
}>();
import type { Component } from 'svelte';
function handleClick() {
dispatch('event');
dispatch('click', 'hello');
interface Props {
// only components that have at most the "prop"
// property required can be passed
component: Component<{ prop: string }>
}
function handleType() {
dispatch('event');
dispatch('type', Math.random() > 0.5 ? 'world' : null);
}
let { component }: Props = $props();
</script>
<button on:click={handleClick} on:keydown={handleType}>Click</button>
<svelte:component this={component} prop="foo" />
```
Closely related to the `Component` type is the `ComponentProps` type which extracts the properties a component expects.
```ts
import type { Component, ComponentProps } from 'svelte';
import MyComponent from './MyComponent.svelte';
function withProps<TComponent extends Component<any>>(
component: TComponent,
props: ComponentProps<TComponent>
) {}
// Errors if the second argument is not the correct props expected
// by the component in the first argument.
withProps(MyComponent, { foo: 'bar' });
```
## Enhancing built-in DOM types
Svelte provides a best effort of all the HTML DOM types that exist. Sometimes you may want to use experimental attributes or custom events coming from an action. In these cases, TypeScript will throw a type error, saying that it does not know these types. If it's a non-experimental standard attribute/event, this may very well be a missing typing from our [HTML typings](https://github.com/sveltejs/svelte/blob/master/packages/svelte/elements.d.ts). In that case, you are welcome to open an issue and/or a PR fixing it.
Svelte provides a best effort of all the HTML DOM types that exist. Sometimes you may want to use experimental attributes or custom events coming from an action. In these cases, TypeScript will throw a type error, saying that it does not know these types. If it's a non-experimental standard attribute/event, this may very well be a missing typing from our [HTML typings](https://github.com/sveltejs/svelte/blob/main/packages/svelte/elements.d.ts). In that case, you are welcome to open an issue and/or a PR fixing it.
In case this is a custom or experimental attribute/event, you can enhance the typings like this:
@ -140,7 +220,7 @@ declare namespace svelteHTML {
Then make sure that `d.ts` file is referenced in your `tsconfig.json`. If it reads something like `"include": ["src/**/*"]` and your `d.ts` file is inside `src`, it should work. You may need to reload for the changes to take effect.
Since Svelte version 4.2 / `svelte-check` version 3.5 / VS Code extension version 107.10.0 you can also declare the typings by augmenting the `svelte/elements` module like this:
You can also declare the typings by augmenting the `svelte/elements` module like this:
```ts
/// file: additional-svelte-typings.d.ts
@ -159,54 +239,3 @@ declare module 'svelte/elements' {
export {}; // ensure this is not an ambient module, else types will be overridden instead of augmented
```
## Experimental advanced typings
A few features are missing from taking full advantage of TypeScript in more advanced use cases like typing that a component implements a certain interface, explicitly typing slots, or using generics. These things are possible using experimental advanced type capabilities. See [this RFC](https://github.com/dummdidumm/rfcs/blob/ts-typedefs-within-svelte-components/text/ts-typing-props-slots-events.md) for more information on how to make use of them.
> The API is experimental and may change at any point
## Limitations
### No TS in markup
You cannot use TypeScript in your template's markup. For example, the following does not work:
```svelte
<script lang="ts">
let count = 10;
</script>
<h1>Count as string: {count as string}!</h1> <!-- ❌ Does not work -->
{#if count > 4}
{@const countString: string = count} <!-- ❌ Does not work -->
{countString}
{/if}
```
### Reactive Declarations
You cannot type your reactive declarations with TypeScript in the way you type a variable. For example, the following does not work:
```svelte
<script lang="ts">
let count = 0;
$: doubled: number = count * 2; // ❌ Does not work
</script>
```
You cannot add a `: TYPE` because it's invalid syntax in this position. Instead, you can move the definition to a `let` statement just above:
```svelte
<script lang="ts">
let count = 0;
let doubled: number;
$: doubled = count * 2;
</script>
```
## Types
> TYPES: svelte

@ -1,18 +1,16 @@
---
title: 'Custom elements API'
title: Custom elements
---
- [basically what we have today](https://svelte.dev/docs/custom-elements-api)
Svelte components can also be compiled to custom elements (aka web components) using the `customElement: true` compiler option. You should specify a tag name for the component using the `<svelte:options>` [element](/docs/special-elements#svelte-options).
```svelte
<svelte:options customElement="my-element" />
<!-- in Svelte 3, do this instead:
<svelte:options tag="my-element" />
-->
<script>
export let name = 'world';
let { name = 'world' } = $props();
</script>
<h1>Hello {name}!</h1>
@ -26,8 +24,6 @@ You can leave out the tag name for any of your inner components which you don't
import MyElement from './MyElement.svelte';
customElements.define('my-element', MyElement.element);
// In Svelte 3, do this instead:
// customElements.define('my-element', MyElement);
```
Once a custom element has been defined, it can be used as a regular DOM element:
@ -40,9 +36,7 @@ document.body.innerHTML = `
`;
```
By default, custom elements are compiled with `accessors: true`, which means that any [props](/docs/basic-markup#attributes-and-props) are exposed as properties of the DOM element (as well as being readable/writable as attributes, where possible).
To prevent this, add `accessors={false}` to `<svelte:options>`.
Any [props](/docs/svelte/template-syntax/basic-markup#attributes-and-props) are exposed as properties of the DOM element (as well as being readable/writable as attributes, where possible).
```js
// @noErrors
@ -108,8 +102,7 @@ When constructing a custom element, you can tailor several aspects by defining `
/>
<script>
export let elementIndex;
export let attachedInternals;
let { elementIndex, attachedInternals } = $props();
// ...
function check() {
attachedInternals.checkValidity();
@ -127,6 +120,6 @@ Custom elements can be a useful way to package components for consumption in a n
- Instead of being extracted out as a separate .css file, styles are inlined into the component as a JavaScript string
- Custom elements are not generally suitable for server-side rendering, as the shadow DOM is invisible until JavaScript loads
- In Svelte, slotted content renders _lazily_. In the DOM, it renders _eagerly_. In other words, it will always be created even if the component's `<slot>` element is inside an `{#if ...}` block. Similarly, including a `<slot>` in an `{#each ...}` block will not cause the slotted content to be rendered multiple times
- The `let:` directive has no effect, because custom elements do not have a way to pass data to the parent component that fills the slot
- The deprecated `let:` directive has no effect, because custom elements do not have a way to pass data to the parent component that fills the slot
- Polyfills are required to support older browsers
- You can use Svelte's context feature between regular Svelte components within a custom element, but you can't use them across custom elements. In other words, you can't use `setContext` on a parent custom element and read that with `getContext` in a child custom element.

@ -1,245 +0,0 @@
---
title: Svelte 4 migration guide
---
This migration guide provides an overview of how to migrate from Svelte version 3 to 4. See the linked PRs for more details about each change. Use the migration script to migrate some of these automatically: `npx svelte-migrate@latest svelte-4`
If you're a library author, consider whether to only support Svelte 4 or if it's possible to support Svelte 3 too. Since most of the breaking changes don't affect many people, this may be easily possible. Also remember to update the version range in your `peerDependencies`.
## Minimum version requirements
- Upgrade to Node 16 or higher. Earlier versions are no longer supported. ([#8566](https://github.com/sveltejs/svelte/issues/8566))
- If you are using SvelteKit, upgrade to 1.20.4 or newer ([sveltejs/kit#10172](https://github.com/sveltejs/kit/pull/10172))
- If you are using Vite without SvelteKit, upgrade to `vite-plugin-svelte` 2.4.1 or newer ([#8516](https://github.com/sveltejs/svelte/issues/8516))
- If you are using webpack, upgrade to webpack 5 or higher and `svelte-loader` 3.1.8 or higher. Earlier versions are no longer supported. ([#8515](https://github.com/sveltejs/svelte/issues/8515), [198dbcf](https://github.com/sveltejs/svelte/commit/198dbcf))
- If you are using Rollup, upgrade to `rollup-plugin-svelte` 7.1.5 or higher ([198dbcf](https://github.com/sveltejs/svelte/commit/198dbcf))
- If you are using TypeScript, upgrade to TypeScript 5 or higher. Lower versions might still work, but no guarantees are made about that. ([#8488](https://github.com/sveltejs/svelte/issues/8488))
## Browser conditions for bundlers
Bundlers must now specify the `browser` condition when building a frontend bundle for the browser. SvelteKit and Vite will handle this automatically for you. If you're using any others, you may observe lifecycle callbacks such as `onMount` not get called and you'll need to update the module resolution configuration.
- For Rollup this is done within the `@rollup/plugin-node-resolve` plugin by setting `browser: true` in its options. See the [`rollup-plugin-svelte`](https://github.com/sveltejs/rollup-plugin-svelte/#usage) documentation for more details
- For wepback this is done by adding `"browser"` to the `conditionNames` array. You may also have to update your `alias` config, if you have set it. See the [`svelte-loader`](https://github.com/sveltejs/svelte-loader#usage) documentation for more details
([#8516](https://github.com/sveltejs/svelte/issues/8516))
## Removal of CJS related output
Svelte no longer supports the CommonJS (CJS) format for compiler output and has also removed the `svelte/register` hook and the CJS runtime version. If you need to stay on the CJS output format, consider using a bundler to convert Svelte's ESM output to CJS in a post-build step. ([#8613](https://github.com/sveltejs/svelte/issues/8613))
## Stricter types for Svelte functions
There are now stricter types for `createEventDispatcher`, `Action`, `ActionReturn`, and `onMount`:
- `createEventDispatcher` now supports specifying that a payload is optional, required, or non-existent, and the call sites are checked accordingly ([#7224](https://github.com/sveltejs/svelte/issues/7224))
```ts
// @errors: 2554 2345
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher<{
optional: number | null;
required: string;
noArgument: null;
}>();
// Svelte version 3:
dispatch('optional');
dispatch('required'); // I can still omit the detail argument
dispatch('noArgument', 'surprise'); // I can still add a detail argument
// Svelte version 4 using TypeScript strict mode:
dispatch('optional');
dispatch('required'); // error, missing argument
dispatch('noArgument', 'surprise'); // error, cannot pass an argument
```
- `Action` and `ActionReturn` have a default parameter type of `undefined` now, which means you need to type the generic if you want to specify that this action receives a parameter. The migration script will migrate this automatically ([#7442](https://github.com/sveltejs/svelte/pull/7442))
```diff
-const action: Action = (node, params) => { .. } // this is now an error if you use params in any way
+const action: Action<HTMLElement, string> = (node, params) => { .. } // params is of type string
```
- `onMount` now shows a type error if you return a function asynchronously from it, because this is likely a bug in your code where you expect the callback to be called on destroy, which it will only do for synchronously returned functions ([#8136](https://github.com/sveltejs/svelte/issues/8136))
```diff
// Example where this change reveals an actual bug
onMount(
- // someCleanup() not called because function handed to onMount is async
- async () => {
- const something = await foo();
+ // someCleanup() is called because function handed to onMount is sync
+ () => {
+ foo().then(something => ..
// ..
return () => someCleanup();
}
);
```
## Custom Elements with Svelte
The creation of custom elements with Svelte has been overhauled and significantly improved. The `tag` option is deprecated in favor of the new `customElement` option:
```diff
-<svelte:options tag="my-component" />
+<svelte:options customElement="my-component" />
```
This change was made to allow [more configurability](custom-elements-api#component-options) for advanced use cases. The migration script will adjust your code automatically. The update timing of properties has changed slightly as well. ([#8457](https://github.com/sveltejs/svelte/issues/8457))
## SvelteComponentTyped is deprecated
`SvelteComponentTyped` is deprecated, as `SvelteComponent` now has all its typing capabilities. Replace all instances of `SvelteComponentTyped` with `SvelteComponent`.
```diff
- import { SvelteComponentTyped } from 'svelte';
+ import { SvelteComponent } from 'svelte';
- export class Foo extends SvelteComponentTyped<{ aProp: string }> {}
+ export class Foo extends SvelteComponent<{ aProp: string }> {}
```
If you have used `SvelteComponent` as the component instance type previously, you may see a somewhat opaque type error now, which is solved by changing `: typeof SvelteComponent` to `: typeof SvelteComponent<any>`.
```diff
<script>
import ComponentA from './ComponentA.svelte';
import ComponentB from './ComponentB.svelte';
import { SvelteComponent } from 'svelte';
- let component: typeof SvelteComponent;
+ let component: typeof SvelteComponent<any>;
function choseRandomly() {
component = Math.random() > 0.5 ? ComponentA : ComponentB;
}
</script>
<button on:click={choseRandomly}>random</button>
<svelte:element this={component} />
```
The migration script will do both automatically for you. ([#8512](https://github.com/sveltejs/svelte/issues/8512))
## Transitions are local by default
Transitions are now local by default to prevent confusion around page navigations. "local" means that a transition will not play if it's within a nested control flow block (`each/if/await/key`) and not the direct parent block but a block above it is created/destroyed. In the following example, the `slide` intro animation will only play when `success` goes from `false` to `true`, but it will _not_ play when `show` goes from `false` to `true`:
```svelte
{#if show}
...
{#if success}
<p in:slide>Success</p>
{/each}
{/if}
```
To make transitions global, add the `|global` modifier - then they will play when _any_ control flow block above is created/destroyed. The migration script will do this automatically for you. ([#6686](https://github.com/sveltejs/svelte/issues/6686))
## Default slot bindings
Default slot bindings are no longer exposed to named slots and vice versa:
```svelte
<script>
import Nested from './Nested.svelte';
</script>
<Nested let:count>
<p>
count in default slot - is available: {count}
</p>
<p slot="bar">
count in bar slot - is not available: {count}
</p>
</Nested>
```
This makes slot bindings more consistent as the behavior is undefined when for example the default slot is from a list and the named slot is not. ([#6049](https://github.com/sveltejs/svelte/issues/6049))
## Preprocessors
The order in which preprocessors are applied has changed. Now, preprocessors are executed in order, and within one group, the order is markup, script, style.
```js
// @errors: 2304
import { preprocess } from 'svelte/compiler';
const { code } = await preprocess(
source,
[
{
markup: () => {
console.log('markup-1');
},
script: () => {
console.log('script-1');
},
style: () => {
console.log('style-1');
}
},
{
markup: () => {
console.log('markup-2');
},
script: () => {
console.log('script-2');
},
style: () => {
console.log('style-2');
}
}
],
{
filename: 'App.svelte'
}
);
// Svelte 3 logs:
// markup-1
// markup-2
// script-1
// script-2
// style-1
// style-2
// Svelte 4 logs:
// markup-1
// script-1
// style-1
// markup-2
// script-2
// style-2
```
This could affect you for example if you are using `MDsveX` - in which case you should make sure it comes before any script or style preprocessor.
```diff
preprocess: [
- vitePreprocess(),
- mdsvex(mdsvexConfig)
+ mdsvex(mdsvexConfig),
+ vitePreprocess()
]
```
Each preprocessor must also have a name. ([#8618](https://github.com/sveltejs/svelte/issues/8618))
## New eslint package
`eslint-plugin-svelte3` is deprecated. It may still work with Svelte 4 but we make no guarantees about that. We recommend switching to our new package [eslint-plugin-svelte](https://github.com/sveltejs/eslint-plugin-svelte). See [this Github post](https://github.com/sveltejs/kit/issues/10242#issuecomment-1610798405) for an instruction how to migrate. Alternatively, you can create a new project using `npm create svelte@latest`, select the eslint (and possibly TypeScript) option and then copy over the related files into your existing project.
## Other breaking changes
- the `inert` attribute is now applied to outroing elements to make them invisible to assistive technology and prevent interaction. ([#8628](https://github.com/sveltejs/svelte/pull/8628))
- the runtime now uses `classList.toggle(name, boolean)` which may not work in very old browsers. Consider using a [polyfill](https://github.com/eligrey/classList.js) if you need to support these browsers. ([#8629](https://github.com/sveltejs/svelte/issues/8629))
- the runtime now uses the `CustomEvent` constructor which may not work in very old browsers. Consider using a [polyfill](https://github.com/theftprevention/event-constructor-polyfill/tree/master) if you need to support these browsers. ([#8775](https://github.com/sveltejs/svelte/pull/8775))
- people implementing their own stores from scratch using the `StartStopNotifier` interface (which is passed to the create function of `writable` etc) from `svelte/store` now need to pass an update function in addition to the set function. This has no effect on people using stores or creating stores using the existing Svelte stores. ([#6750](https://github.com/sveltejs/svelte/issues/6750))
- `derived` will now throw an error on falsy values instead of stores passed to it. ([#7947](https://github.com/sveltejs/svelte/issues/7947))
- type definitions for `svelte/internal` were removed to further discourage usage of those internal methods which are not public API. Most of these will likely change for Svelte 5
- Removal of DOM nodes is now batched which slightly changes its order, which might affect the order of events fired if you're using a `MutationObserver` on these elements ([#8763](https://github.com/sveltejs/svelte/pull/8763))
- if you enhanced the global typings through the `svelte.JSX` namespace before, you need to migrate this to use the `svelteHTML` namespace. Similarly if you used the `svelte.JSX` namespace to use type definitions from it, you need to migrate those to use the types from `svelte/elements` instead. You can find more information about what to do [here](https://github.com/sveltejs/language-tools/blob/master/docs/preprocessors/typescript.md#im-getting-deprecation-warnings-for-sveltejsx--i-want-to-migrate-to-the-new-typings)

@ -0,0 +1,6 @@
---
title: Reactivity indepth
---
- how to think about Runes ("just JavaScript" with added reactivity, what this means for keeping reactivity alive across boundaries)
- signals

@ -0,0 +1,5 @@
---
title: Svelte 5 migration guide
---
- the stuff from the preview docs and possibly more

@ -0,0 +1,3 @@
---
title: Misc
---

@ -1,3 +0,0 @@
{
"title": "Misc"
}

@ -1,30 +0,0 @@
---
title: 'svelte/register'
---
> This API is removed in Svelte 4. `require` hooks are deprecated and current Node versions understand ESM. Use a bundler like Vite or our full-stack framework [SvelteKit](https://kit.svelte.dev) instead to create JavaScript modules from Svelte components.
To render Svelte components in Node.js without bundling, use `require('svelte/register')`. After that, you can use `require` to include any `.svelte` file.
```js
// @noErrors
require('svelte/register');
const App = require('./App.svelte').default;
// ...
const { html, css, head } = App.render({ answer: 42 });
```
> The `.default` is necessary because we're converting from native JavaScript modules to the CommonJS modules recognised by Node. Note that if your component imports JavaScript modules, they will fail to load in Node and you will need to use a bundler instead.
To set compile options, or to use a custom file extension, call the `register` hook as a function:
```js
// @noErrors
require('svelte/register')({
extensions: ['.customextension'], // defaults to ['.html', '.svelte']
preserveComments: true
});
```

@ -1,3 +0,0 @@
{
"title": "Legacy"
}

@ -0,0 +1,9 @@
---
title: $state
---
TODO
- add other pages
- figure out a way to get separator titles in here, so we can have a 'runes' section and an 'imports' section and an 'errors/warnings' section without introducing another layer of nesting
- figure out a good way to import reference docs from other repos that works locally and in prod

@ -0,0 +1,5 @@
---
title: svelte
---
<!-- @include svelte -->

@ -0,0 +1,5 @@
---
title: svelte/action
---
<!-- @include svelte/action -->

@ -0,0 +1,5 @@
---
title: svelte/animate
---
<!-- @include svelte/animate -->

@ -0,0 +1,5 @@
---
title: svelte/compiler
---
<!-- @include svelte/compiler -->

@ -0,0 +1,5 @@
---
title: svelte/easing
---
<!-- @include svelte/easing -->

@ -0,0 +1,5 @@
---
title: svelte/events
---
<!-- @include svelte/events -->

@ -0,0 +1,5 @@
---
title: svelte/legacy
---
<!-- @include svelte/legacy -->

@ -0,0 +1,5 @@
---
title: svelte/motion
---
<!-- @include svelte/motion -->

@ -0,0 +1,5 @@
---
title: svelte/reactivity
---
<!-- @include svelte/reactivity -->

@ -0,0 +1,5 @@
---
title: svelte/server
---
<!-- @include svelte/server -->

@ -0,0 +1,5 @@
---
title: svelte/store
---
<!-- @include svelte/store -->

@ -0,0 +1,5 @@
---
title: svelte/transition
---
<!-- @include svelte/transition -->

@ -0,0 +1,3 @@
---
title: Reference
---

@ -0,0 +1,3 @@
---
title: Svelte
---
Loading…
Cancel
Save