Svelte language preview
1. TypeScript script block
horizon-dark
<script lang="ts">
type Box = { width: number; height: number };
let boxes: Box[] = [
{ width: 3, height: 4 },
{ width: 5, height: 7 },
];
</script>atom-one-dark
<script lang="ts">
type Box = { width: number; height: number };
let boxes: Box[] = [
{ width: 3, height: 4 },
{ width: 5, height: 7 },
];
</script>github-dark
<script lang="ts">
type Box = { width: number; height: number };
let boxes: Box[] = [
{ width: 3, height: 4 },
{ width: 5, height: 7 },
];
</script>dracula
<script lang="ts">
type Box = { width: number; height: number };
let boxes: Box[] = [
{ width: 3, height: 4 },
{ width: 5, height: 7 },
];
</script>nord
<script lang="ts">
type Box = { width: number; height: number };
let boxes: Box[] = [
{ width: 3, height: 4 },
{ width: 5, height: 7 },
];
</script>github
<script lang="ts">
type Box = { width: number; height: number };
let boxes: Box[] = [
{ width: 3, height: 4 },
{ width: 5, height: 7 },
];
</script>2. Module TypeScript script
horizon-dark
<script lang="ts" context="module">
export const API_URL: string = "https://example.com";
</script>atom-one-dark
<script lang="ts" context="module">
export const API_URL: string = "https://example.com";
</script>github-dark
<script lang="ts" context="module">
export const API_URL: string = "https://example.com";
</script>dracula
<script lang="ts" context="module">
export const API_URL: string = "https://example.com";
</script>nord
<script lang="ts" context="module">
export const API_URL: string = "https://example.com";
</script>github
<script lang="ts" context="module">
export const API_URL: string = "https://example.com";
</script>3. lang="typescript"
horizon-dark
<script lang="typescript">
let count: number = 0;
</script>atom-one-dark
<script lang="typescript">
let count: number = 0;
</script>github-dark
<script lang="typescript">
let count: number = 0;
</script>dracula
<script lang="typescript">
let count: number = 0;
</script>nord
<script lang="typescript">
let count: number = 0;
</script>github
<script lang="typescript">
let count: number = 0;
</script>4. Svelte 5 declaration tags
horizon-dark
<script lang="ts">
type Box = { width: number; height: number };
let boxes: Box[] = [
{ width: 3, height: 4 },
{ width: 5, height: 7 },
];
</script>
{#each boxes as box}
{const area = box.width * box.height}
{let label: number = $state(`${area} square pixels`)}
{const doubled: string = area * 2}
<p>{doubled === 1} {label === "large"}</p>
<div>
{const area = "nested"}
{area}
</div>
{/each}atom-one-dark
<script lang="ts">
type Box = { width: number; height: number };
let boxes: Box[] = [
{ width: 3, height: 4 },
{ width: 5, height: 7 },
];
</script>
{#each boxes as box}
{const area = box.width * box.height}
{let label: number = $state(`${area} square pixels`)}
{const doubled: string = area * 2}
<p>{doubled === 1} {label === "large"}</p>
<div>
{const area = "nested"}
{area}
</div>
{/each}github-dark
<script lang="ts">
type Box = { width: number; height: number };
let boxes: Box[] = [
{ width: 3, height: 4 },
{ width: 5, height: 7 },
];
</script>
{#each boxes as box}
{const area = box.width * box.height}
{let label: number = $state(`${area} square pixels`)}
{const doubled: string = area * 2}
<p>{doubled === 1} {label === "large"}</p>
<div>
{const area = "nested"}
{area}
</div>
{/each}dracula
<script lang="ts">
type Box = { width: number; height: number };
let boxes: Box[] = [
{ width: 3, height: 4 },
{ width: 5, height: 7 },
];
</script>
{#each boxes as box}
{const area = box.width * box.height}
{let label: number = $state(`${area} square pixels`)}
{const doubled: string = area * 2}
<p>{doubled === 1} {label === "large"}</p>
<div>
{const area = "nested"}
{area}
</div>
{/each}nord
<script lang="ts">
type Box = { width: number; height: number };
let boxes: Box[] = [
{ width: 3, height: 4 },
{ width: 5, height: 7 },
];
</script>
{#each boxes as box}
{const area = box.width * box.height}
{let label: number = $state(`${area} square pixels`)}
{const doubled: string = area * 2}
<p>{doubled === 1} {label === "large"}</p>
<div>
{const area = "nested"}
{area}
</div>
{/each}github
<script lang="ts">
type Box = { width: number; height: number };
let boxes: Box[] = [
{ width: 3, height: 4 },
{ width: 5, height: 7 },
];
</script>
{#each boxes as box}
{const area = box.width * box.height}
{let label: number = $state(`${area} square pixels`)}
{const doubled: string = area * 2}
<p>{doubled === 1} {label === "large"}</p>
<div>
{const area = "nested"}
{area}
</div>
{/each}5. Runes and block syntax
horizon-dark
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<button onclick={() => count++}>{doubled}</button>
{#if count}
{@render children()}
{:else if count > 10}
<p>many</p>
{:else}
<p>few</p>
{/if}atom-one-dark
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<button onclick={() => count++}>{doubled}</button>
{#if count}
{@render children()}
{:else if count > 10}
<p>many</p>
{:else}
<p>few</p>
{/if}github-dark
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<button onclick={() => count++}>{doubled}</button>
{#if count}
{@render children()}
{:else if count > 10}
<p>many</p>
{:else}
<p>few</p>
{/if}dracula
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<button onclick={() => count++}>{doubled}</button>
{#if count}
{@render children()}
{:else if count > 10}
<p>many</p>
{:else}
<p>few</p>
{/if}nord
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<button onclick={() => count++}>{doubled}</button>
{#if count}
{@render children()}
{:else if count > 10}
<p>many</p>
{:else}
<p>few</p>
{/if}github
<script>
let count = $state(0);
let doubled = $derived(count * 2);
</script>
<button onclick={() => count++}>{doubled}</button>
{#if count}
{@render children()}
{:else if count > 10}
<p>many</p>
{:else}
<p>few</p>
{/if}6. Dotted rune suffixes
horizon-dark
<script>
let count = $state.raw(0);
let doubled = $derived.by(() => count * 2);
$effect.pre(() => {
console.log("before DOM update");
});
$effect(() => {
if ($effect.tracking()) {
console.log("running inside a tracking context");
}
});
const id = $props.id();
</script>atom-one-dark
<script>
let count = $state.raw(0);
let doubled = $derived.by(() => count * 2);
$effect.pre(() => {
console.log("before DOM update");
});
$effect(() => {
if ($effect.tracking()) {
console.log("running inside a tracking context");
}
});
const id = $props.id();
</script>github-dark
<script>
let count = $state.raw(0);
let doubled = $derived.by(() => count * 2);
$effect.pre(() => {
console.log("before DOM update");
});
$effect(() => {
if ($effect.tracking()) {
console.log("running inside a tracking context");
}
});
const id = $props.id();
</script>dracula
<script>
let count = $state.raw(0);
let doubled = $derived.by(() => count * 2);
$effect.pre(() => {
console.log("before DOM update");
});
$effect(() => {
if ($effect.tracking()) {
console.log("running inside a tracking context");
}
});
const id = $props.id();
</script>nord
<script>
let count = $state.raw(0);
let doubled = $derived.by(() => count * 2);
$effect.pre(() => {
console.log("before DOM update");
});
$effect(() => {
if ($effect.tracking()) {
console.log("running inside a tracking context");
}
});
const id = $props.id();
</script>github
<script>
let count = $state.raw(0);
let doubled = $derived.by(() => count * 2);
$effect.pre(() => {
console.log("before DOM update");
});
$effect(() => {
if ($effect.tracking()) {
console.log("running inside a tracking context");
}
});
const id = $props.id();
</script>7. Typed rune calls
horizon-dark
<script lang="ts">
type Item = { id: number; label: string };
let count = $state<number>(0);
let items = $derived<Item[]>(
Array.from({ length: count }, (_, id) => ({ id, label: `Item ${id}` })),
);
</script>
<p>{items.length} items</p>atom-one-dark
<script lang="ts">
type Item = { id: number; label: string };
let count = $state<number>(0);
let items = $derived<Item[]>(
Array.from({ length: count }, (_, id) => ({ id, label: `Item ${id}` })),
);
</script>
<p>{items.length} items</p>github-dark
<script lang="ts">
type Item = { id: number; label: string };
let count = $state<number>(0);
let items = $derived<Item[]>(
Array.from({ length: count }, (_, id) => ({ id, label: `Item ${id}` })),
);
</script>
<p>{items.length} items</p>dracula
<script lang="ts">
type Item = { id: number; label: string };
let count = $state<number>(0);
let items = $derived<Item[]>(
Array.from({ length: count }, (_, id) => ({ id, label: `Item ${id}` })),
);
</script>
<p>{items.length} items</p>nord
<script lang="ts">
type Item = { id: number; label: string };
let count = $state<number>(0);
let items = $derived<Item[]>(
Array.from({ length: count }, (_, id) => ({ id, label: `Item ${id}` })),
);
</script>
<p>{items.length} items</p>github
<script lang="ts">
type Item = { id: number; label: string };
let count = $state<number>(0);
let items = $derived<Item[]>(
Array.from({ length: count }, (_, id) => ({ id, label: `Item ${id}` })),
);
</script>
<p>{items.length} items</p>8. Legacy directives
horizon-dark
<script>
let count = 0;
let name = "";
let visible = true;
function increment() {
count += 1;
}
function focus(node) {
node.focus();
}
</script>
<button on:click={increment}>Clicks: {count}</button>
<input bind:value={name} placeholder="Name" />
<div class:active={count > 0} class="box">{name || "Anonymous"}</div>
<input use:focus />
{#if visible}
<p transition:fade>Hello, {name}!</p>
{/if}
<List {items} let:item>
<span>{item.label}</span>
</List>atom-one-dark
<script>
let count = 0;
let name = "";
let visible = true;
function increment() {
count += 1;
}
function focus(node) {
node.focus();
}
</script>
<button on:click={increment}>Clicks: {count}</button>
<input bind:value={name} placeholder="Name" />
<div class:active={count > 0} class="box">{name || "Anonymous"}</div>
<input use:focus />
{#if visible}
<p transition:fade>Hello, {name}!</p>
{/if}
<List {items} let:item>
<span>{item.label}</span>
</List>github-dark
<script>
let count = 0;
let name = "";
let visible = true;
function increment() {
count += 1;
}
function focus(node) {
node.focus();
}
</script>
<button on:click={increment}>Clicks: {count}</button>
<input bind:value={name} placeholder="Name" />
<div class:active={count > 0} class="box">{name || "Anonymous"}</div>
<input use:focus />
{#if visible}
<p transition:fade>Hello, {name}!</p>
{/if}
<List {items} let:item>
<span>{item.label}</span>
</List>dracula
<script>
let count = 0;
let name = "";
let visible = true;
function increment() {
count += 1;
}
function focus(node) {
node.focus();
}
</script>
<button on:click={increment}>Clicks: {count}</button>
<input bind:value={name} placeholder="Name" />
<div class:active={count > 0} class="box">{name || "Anonymous"}</div>
<input use:focus />
{#if visible}
<p transition:fade>Hello, {name}!</p>
{/if}
<List {items} let:item>
<span>{item.label}</span>
</List>nord
<script>
let count = 0;
let name = "";
let visible = true;
function increment() {
count += 1;
}
function focus(node) {
node.focus();
}
</script>
<button on:click={increment}>Clicks: {count}</button>
<input bind:value={name} placeholder="Name" />
<div class:active={count > 0} class="box">{name || "Anonymous"}</div>
<input use:focus />
{#if visible}
<p transition:fade>Hello, {name}!</p>
{/if}
<List {items} let:item>
<span>{item.label}</span>
</List>github
<script>
let count = 0;
let name = "";
let visible = true;
function increment() {
count += 1;
}
function focus(node) {
node.focus();
}
</script>
<button on:click={increment}>Clicks: {count}</button>
<input bind:value={name} placeholder="Name" />
<div class:active={count > 0} class="box">{name || "Anonymous"}</div>
<input use:focus />
{#if visible}
<p transition:fade>Hello, {name}!</p>
{/if}
<List {items} let:item>
<span>{item.label}</span>
</List>9. Store auto-subscription
horizon-dark
<script>
import { writable } from "svelte/store";
const count = writable(0);
function increment() {
$count += 1;
}
</script>
<button on:click={increment}>{$count}</button>
<p>{$count > 10 ? "big" : "small"}</p>
<p>Previous value: {$count-1}</p>atom-one-dark
<script>
import { writable } from "svelte/store";
const count = writable(0);
function increment() {
$count += 1;
}
</script>
<button on:click={increment}>{$count}</button>
<p>{$count > 10 ? "big" : "small"}</p>
<p>Previous value: {$count-1}</p>github-dark
<script>
import { writable } from "svelte/store";
const count = writable(0);
function increment() {
$count += 1;
}
</script>
<button on:click={increment}>{$count}</button>
<p>{$count > 10 ? "big" : "small"}</p>
<p>Previous value: {$count-1}</p>dracula
<script>
import { writable } from "svelte/store";
const count = writable(0);
function increment() {
$count += 1;
}
</script>
<button on:click={increment}>{$count}</button>
<p>{$count > 10 ? "big" : "small"}</p>
<p>Previous value: {$count-1}</p>nord
<script>
import { writable } from "svelte/store";
const count = writable(0);
function increment() {
$count += 1;
}
</script>
<button on:click={increment}>{$count}</button>
<p>{$count > 10 ? "big" : "small"}</p>
<p>Previous value: {$count-1}</p>github
<script>
import { writable } from "svelte/store";
const count = writable(0);
function increment() {
$count += 1;
}
</script>
<button on:click={increment}>{$count}</button>
<p>{$count > 10 ? "big" : "small"}</p>
<p>Previous value: {$count-1}</p>Kitchen sink
horizon-dark
<script lang="ts" module>
export const APP_VERSION: string = "1.0.0";
</script>
<script lang="ts">
import type { Snippet } from "svelte";
import { fade, fly } from "svelte/transition";
import { tweened } from "svelte/motion";
import { writable } from "svelte/store";
type Item = { id: number; label: string };
interface Props {
title: string;
items?: Item[];
children?: Snippet;
header?: Snippet<[string]>;
}
let { title, items = [], children, header }: Props = $props();
let count = $state(0);
let name = $bindable("");
let legacyCount = 0;
let doubled = $derived(count * 2);
let trustedMarkup = "<strong>safe html</strong>";
const total = $derived.by(() => items.length + count);
const store = writable(0);
const tweenedValue = tweened(0);
$effect(() => {
console.log("count", count);
});
$effect.pre(() => {
document.title = title;
});
$inspect(count, doubled);
function increment() {
count += 1;
}
function focus(node: HTMLInputElement) {
node.focus();
}
async function loadItems(): Promise<Item[]> {
return items;
}
</script>
<svelte:options runes={true} />
<svelte:head>
<title>{title}</title>
<!-- App metadata -->
</svelte:head>
<svelte:window onkeydown={(e) => e.key === "Escape" && (count = 0)} />
<style>
.box {
padding: 1rem;
border: 1px solid #ccc;
}
.active {
font-weight: bold;
}
:global(body) {
margin: 0;
}
</style>
{@debug count, name, doubled}
{#snippet row(item: Item, index: number)}
<li>{index + 1}. {item.label}</li>
{/snippet}
{#if header}
{@render header(title)}
{/if}
<!-- Legacy directives alongside Svelte 5 -->
<button
on:click={() => (legacyCount += 1)}
onclick={increment}
onkeydown={(e) => e.key === "Enter" && increment()}
>
Legacy: {legacyCount} · Runes: {count} · {doubled}
</button>
<input bind:value={name} placeholder="Name" />
<div
class:active={count > 0}
class="box"
style:color={count > 5 ? "crimson" : "inherit"}
style:opacity={count / 10}
>
{name || "Anonymous"} · total {total}
</div>
<input use:focus />
{#if count === 0}
<p transition:fade>Start counting</p>
{:else if count < 5}
<p in:fly={{ y: 20, duration: 300 }} out:fade>Getting started</p>
{:else}
<p animate:fade>{count} clicks</p>
{/if}
{#each items as item, index (item.id)}
{@render row(item, index)}
{:else}
<p>No items yet</p>
{/each}
{#key count}
{const badge: string = $state(`v${count}`)}
{let suffix: number = $derived(badge.length)}
<span>{badge} ({suffix})</span>
{/key}
{#await loadItems()}
<p>Loading...</p>
{:then loaded}
<ul>
{#each loaded as item (item.id)}
<li>{item.label}</li>
{/each}
</ul>
{:catch error}
<p class="error">{error.message}</p>
{/await}
<p>Store: {$store}</p>
<p>Tweened: {$tweenedValue}</p>
{#if children}
{@render children()}
{/if}
<Widget {items} let:widget>
<span>{widget.label}</span>
</Widget>
{@html trustedMarkup}
<a href="/about">About</a>atom-one-dark
<script lang="ts" module>
export const APP_VERSION: string = "1.0.0";
</script>
<script lang="ts">
import type { Snippet } from "svelte";
import { fade, fly } from "svelte/transition";
import { tweened } from "svelte/motion";
import { writable } from "svelte/store";
type Item = { id: number; label: string };
interface Props {
title: string;
items?: Item[];
children?: Snippet;
header?: Snippet<[string]>;
}
let { title, items = [], children, header }: Props = $props();
let count = $state(0);
let name = $bindable("");
let legacyCount = 0;
let doubled = $derived(count * 2);
let trustedMarkup = "<strong>safe html</strong>";
const total = $derived.by(() => items.length + count);
const store = writable(0);
const tweenedValue = tweened(0);
$effect(() => {
console.log("count", count);
});
$effect.pre(() => {
document.title = title;
});
$inspect(count, doubled);
function increment() {
count += 1;
}
function focus(node: HTMLInputElement) {
node.focus();
}
async function loadItems(): Promise<Item[]> {
return items;
}
</script>
<svelte:options runes={true} />
<svelte:head>
<title>{title}</title>
<!-- App metadata -->
</svelte:head>
<svelte:window onkeydown={(e) => e.key === "Escape" && (count = 0)} />
<style>
.box {
padding: 1rem;
border: 1px solid #ccc;
}
.active {
font-weight: bold;
}
:global(body) {
margin: 0;
}
</style>
{@debug count, name, doubled}
{#snippet row(item: Item, index: number)}
<li>{index + 1}. {item.label}</li>
{/snippet}
{#if header}
{@render header(title)}
{/if}
<!-- Legacy directives alongside Svelte 5 -->
<button
on:click={() => (legacyCount += 1)}
onclick={increment}
onkeydown={(e) => e.key === "Enter" && increment()}
>
Legacy: {legacyCount} · Runes: {count} · {doubled}
</button>
<input bind:value={name} placeholder="Name" />
<div
class:active={count > 0}
class="box"
style:color={count > 5 ? "crimson" : "inherit"}
style:opacity={count / 10}
>
{name || "Anonymous"} · total {total}
</div>
<input use:focus />
{#if count === 0}
<p transition:fade>Start counting</p>
{:else if count < 5}
<p in:fly={{ y: 20, duration: 300 }} out:fade>Getting started</p>
{:else}
<p animate:fade>{count} clicks</p>
{/if}
{#each items as item, index (item.id)}
{@render row(item, index)}
{:else}
<p>No items yet</p>
{/each}
{#key count}
{const badge: string = $state(`v${count}`)}
{let suffix: number = $derived(badge.length)}
<span>{badge} ({suffix})</span>
{/key}
{#await loadItems()}
<p>Loading...</p>
{:then loaded}
<ul>
{#each loaded as item (item.id)}
<li>{item.label}</li>
{/each}
</ul>
{:catch error}
<p class="error">{error.message}</p>
{/await}
<p>Store: {$store}</p>
<p>Tweened: {$tweenedValue}</p>
{#if children}
{@render children()}
{/if}
<Widget {items} let:widget>
<span>{widget.label}</span>
</Widget>
{@html trustedMarkup}
<a href="/about">About</a>github-dark
<script lang="ts" module>
export const APP_VERSION: string = "1.0.0";
</script>
<script lang="ts">
import type { Snippet } from "svelte";
import { fade, fly } from "svelte/transition";
import { tweened } from "svelte/motion";
import { writable } from "svelte/store";
type Item = { id: number; label: string };
interface Props {
title: string;
items?: Item[];
children?: Snippet;
header?: Snippet<[string]>;
}
let { title, items = [], children, header }: Props = $props();
let count = $state(0);
let name = $bindable("");
let legacyCount = 0;
let doubled = $derived(count * 2);
let trustedMarkup = "<strong>safe html</strong>";
const total = $derived.by(() => items.length + count);
const store = writable(0);
const tweenedValue = tweened(0);
$effect(() => {
console.log("count", count);
});
$effect.pre(() => {
document.title = title;
});
$inspect(count, doubled);
function increment() {
count += 1;
}
function focus(node: HTMLInputElement) {
node.focus();
}
async function loadItems(): Promise<Item[]> {
return items;
}
</script>
<svelte:options runes={true} />
<svelte:head>
<title>{title}</title>
<!-- App metadata -->
</svelte:head>
<svelte:window onkeydown={(e) => e.key === "Escape" && (count = 0)} />
<style>
.box {
padding: 1rem;
border: 1px solid #ccc;
}
.active {
font-weight: bold;
}
:global(body) {
margin: 0;
}
</style>
{@debug count, name, doubled}
{#snippet row(item: Item, index: number)}
<li>{index + 1}. {item.label}</li>
{/snippet}
{#if header}
{@render header(title)}
{/if}
<!-- Legacy directives alongside Svelte 5 -->
<button
on:click={() => (legacyCount += 1)}
onclick={increment}
onkeydown={(e) => e.key === "Enter" && increment()}
>
Legacy: {legacyCount} · Runes: {count} · {doubled}
</button>
<input bind:value={name} placeholder="Name" />
<div
class:active={count > 0}
class="box"
style:color={count > 5 ? "crimson" : "inherit"}
style:opacity={count / 10}
>
{name || "Anonymous"} · total {total}
</div>
<input use:focus />
{#if count === 0}
<p transition:fade>Start counting</p>
{:else if count < 5}
<p in:fly={{ y: 20, duration: 300 }} out:fade>Getting started</p>
{:else}
<p animate:fade>{count} clicks</p>
{/if}
{#each items as item, index (item.id)}
{@render row(item, index)}
{:else}
<p>No items yet</p>
{/each}
{#key count}
{const badge: string = $state(`v${count}`)}
{let suffix: number = $derived(badge.length)}
<span>{badge} ({suffix})</span>
{/key}
{#await loadItems()}
<p>Loading...</p>
{:then loaded}
<ul>
{#each loaded as item (item.id)}
<li>{item.label}</li>
{/each}
</ul>
{:catch error}
<p class="error">{error.message}</p>
{/await}
<p>Store: {$store}</p>
<p>Tweened: {$tweenedValue}</p>
{#if children}
{@render children()}
{/if}
<Widget {items} let:widget>
<span>{widget.label}</span>
</Widget>
{@html trustedMarkup}
<a href="/about">About</a>dracula
<script lang="ts" module>
export const APP_VERSION: string = "1.0.0";
</script>
<script lang="ts">
import type { Snippet } from "svelte";
import { fade, fly } from "svelte/transition";
import { tweened } from "svelte/motion";
import { writable } from "svelte/store";
type Item = { id: number; label: string };
interface Props {
title: string;
items?: Item[];
children?: Snippet;
header?: Snippet<[string]>;
}
let { title, items = [], children, header }: Props = $props();
let count = $state(0);
let name = $bindable("");
let legacyCount = 0;
let doubled = $derived(count * 2);
let trustedMarkup = "<strong>safe html</strong>";
const total = $derived.by(() => items.length + count);
const store = writable(0);
const tweenedValue = tweened(0);
$effect(() => {
console.log("count", count);
});
$effect.pre(() => {
document.title = title;
});
$inspect(count, doubled);
function increment() {
count += 1;
}
function focus(node: HTMLInputElement) {
node.focus();
}
async function loadItems(): Promise<Item[]> {
return items;
}
</script>
<svelte:options runes={true} />
<svelte:head>
<title>{title}</title>
<!-- App metadata -->
</svelte:head>
<svelte:window onkeydown={(e) => e.key === "Escape" && (count = 0)} />
<style>
.box {
padding: 1rem;
border: 1px solid #ccc;
}
.active {
font-weight: bold;
}
:global(body) {
margin: 0;
}
</style>
{@debug count, name, doubled}
{#snippet row(item: Item, index: number)}
<li>{index + 1}. {item.label}</li>
{/snippet}
{#if header}
{@render header(title)}
{/if}
<!-- Legacy directives alongside Svelte 5 -->
<button
on:click={() => (legacyCount += 1)}
onclick={increment}
onkeydown={(e) => e.key === "Enter" && increment()}
>
Legacy: {legacyCount} · Runes: {count} · {doubled}
</button>
<input bind:value={name} placeholder="Name" />
<div
class:active={count > 0}
class="box"
style:color={count > 5 ? "crimson" : "inherit"}
style:opacity={count / 10}
>
{name || "Anonymous"} · total {total}
</div>
<input use:focus />
{#if count === 0}
<p transition:fade>Start counting</p>
{:else if count < 5}
<p in:fly={{ y: 20, duration: 300 }} out:fade>Getting started</p>
{:else}
<p animate:fade>{count} clicks</p>
{/if}
{#each items as item, index (item.id)}
{@render row(item, index)}
{:else}
<p>No items yet</p>
{/each}
{#key count}
{const badge: string = $state(`v${count}`)}
{let suffix: number = $derived(badge.length)}
<span>{badge} ({suffix})</span>
{/key}
{#await loadItems()}
<p>Loading...</p>
{:then loaded}
<ul>
{#each loaded as item (item.id)}
<li>{item.label}</li>
{/each}
</ul>
{:catch error}
<p class="error">{error.message}</p>
{/await}
<p>Store: {$store}</p>
<p>Tweened: {$tweenedValue}</p>
{#if children}
{@render children()}
{/if}
<Widget {items} let:widget>
<span>{widget.label}</span>
</Widget>
{@html trustedMarkup}
<a href="/about">About</a>nord
<script lang="ts" module>
export const APP_VERSION: string = "1.0.0";
</script>
<script lang="ts">
import type { Snippet } from "svelte";
import { fade, fly } from "svelte/transition";
import { tweened } from "svelte/motion";
import { writable } from "svelte/store";
type Item = { id: number; label: string };
interface Props {
title: string;
items?: Item[];
children?: Snippet;
header?: Snippet<[string]>;
}
let { title, items = [], children, header }: Props = $props();
let count = $state(0);
let name = $bindable("");
let legacyCount = 0;
let doubled = $derived(count * 2);
let trustedMarkup = "<strong>safe html</strong>";
const total = $derived.by(() => items.length + count);
const store = writable(0);
const tweenedValue = tweened(0);
$effect(() => {
console.log("count", count);
});
$effect.pre(() => {
document.title = title;
});
$inspect(count, doubled);
function increment() {
count += 1;
}
function focus(node: HTMLInputElement) {
node.focus();
}
async function loadItems(): Promise<Item[]> {
return items;
}
</script>
<svelte:options runes={true} />
<svelte:head>
<title>{title}</title>
<!-- App metadata -->
</svelte:head>
<svelte:window onkeydown={(e) => e.key === "Escape" && (count = 0)} />
<style>
.box {
padding: 1rem;
border: 1px solid #ccc;
}
.active {
font-weight: bold;
}
:global(body) {
margin: 0;
}
</style>
{@debug count, name, doubled}
{#snippet row(item: Item, index: number)}
<li>{index + 1}. {item.label}</li>
{/snippet}
{#if header}
{@render header(title)}
{/if}
<!-- Legacy directives alongside Svelte 5 -->
<button
on:click={() => (legacyCount += 1)}
onclick={increment}
onkeydown={(e) => e.key === "Enter" && increment()}
>
Legacy: {legacyCount} · Runes: {count} · {doubled}
</button>
<input bind:value={name} placeholder="Name" />
<div
class:active={count > 0}
class="box"
style:color={count > 5 ? "crimson" : "inherit"}
style:opacity={count / 10}
>
{name || "Anonymous"} · total {total}
</div>
<input use:focus />
{#if count === 0}
<p transition:fade>Start counting</p>
{:else if count < 5}
<p in:fly={{ y: 20, duration: 300 }} out:fade>Getting started</p>
{:else}
<p animate:fade>{count} clicks</p>
{/if}
{#each items as item, index (item.id)}
{@render row(item, index)}
{:else}
<p>No items yet</p>
{/each}
{#key count}
{const badge: string = $state(`v${count}`)}
{let suffix: number = $derived(badge.length)}
<span>{badge} ({suffix})</span>
{/key}
{#await loadItems()}
<p>Loading...</p>
{:then loaded}
<ul>
{#each loaded as item (item.id)}
<li>{item.label}</li>
{/each}
</ul>
{:catch error}
<p class="error">{error.message}</p>
{/await}
<p>Store: {$store}</p>
<p>Tweened: {$tweenedValue}</p>
{#if children}
{@render children()}
{/if}
<Widget {items} let:widget>
<span>{widget.label}</span>
</Widget>
{@html trustedMarkup}
<a href="/about">About</a>github
<script lang="ts" module>
export const APP_VERSION: string = "1.0.0";
</script>
<script lang="ts">
import type { Snippet } from "svelte";
import { fade, fly } from "svelte/transition";
import { tweened } from "svelte/motion";
import { writable } from "svelte/store";
type Item = { id: number; label: string };
interface Props {
title: string;
items?: Item[];
children?: Snippet;
header?: Snippet<[string]>;
}
let { title, items = [], children, header }: Props = $props();
let count = $state(0);
let name = $bindable("");
let legacyCount = 0;
let doubled = $derived(count * 2);
let trustedMarkup = "<strong>safe html</strong>";
const total = $derived.by(() => items.length + count);
const store = writable(0);
const tweenedValue = tweened(0);
$effect(() => {
console.log("count", count);
});
$effect.pre(() => {
document.title = title;
});
$inspect(count, doubled);
function increment() {
count += 1;
}
function focus(node: HTMLInputElement) {
node.focus();
}
async function loadItems(): Promise<Item[]> {
return items;
}
</script>
<svelte:options runes={true} />
<svelte:head>
<title>{title}</title>
<!-- App metadata -->
</svelte:head>
<svelte:window onkeydown={(e) => e.key === "Escape" && (count = 0)} />
<style>
.box {
padding: 1rem;
border: 1px solid #ccc;
}
.active {
font-weight: bold;
}
:global(body) {
margin: 0;
}
</style>
{@debug count, name, doubled}
{#snippet row(item: Item, index: number)}
<li>{index + 1}. {item.label}</li>
{/snippet}
{#if header}
{@render header(title)}
{/if}
<!-- Legacy directives alongside Svelte 5 -->
<button
on:click={() => (legacyCount += 1)}
onclick={increment}
onkeydown={(e) => e.key === "Enter" && increment()}
>
Legacy: {legacyCount} · Runes: {count} · {doubled}
</button>
<input bind:value={name} placeholder="Name" />
<div
class:active={count > 0}
class="box"
style:color={count > 5 ? "crimson" : "inherit"}
style:opacity={count / 10}
>
{name || "Anonymous"} · total {total}
</div>
<input use:focus />
{#if count === 0}
<p transition:fade>Start counting</p>
{:else if count < 5}
<p in:fly={{ y: 20, duration: 300 }} out:fade>Getting started</p>
{:else}
<p animate:fade>{count} clicks</p>
{/if}
{#each items as item, index (item.id)}
{@render row(item, index)}
{:else}
<p>No items yet</p>
{/each}
{#key count}
{const badge: string = $state(`v${count}`)}
{let suffix: number = $derived(badge.length)}
<span>{badge} ({suffix})</span>
{/key}
{#await loadItems()}
<p>Loading...</p>
{:then loaded}
<ul>
{#each loaded as item (item.id)}
<li>{item.label}</li>
{/each}
</ul>
{:catch error}
<p class="error">{error.message}</p>
{/await}
<p>Store: {$store}</p>
<p>Tweened: {$tweenedValue}</p>
{#if children}
{@render children()}
{/if}
<Widget {items} let:widget>
<span>{widget.label}</span>
</Widget>
{@html trustedMarkup}
<a href="/about">About</a>