Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ class Todo {
}
```

> !LEGACY
> In Svelte 4, state was implicitly reactive if the variable was declared at the top level
>
> ```svelte
> <script>
> let count = 0;
> </script>
>
> <button on:click={() => count++}>
> clicks: {count}
> </button>
> ```

## `$derived`

Derived state is declared with the `$derived` rune:
Expand All @@ -61,6 +74,24 @@ The expression inside `$derived(...)` should be free of side-effects. Svelte wil

As with `$state`, you can mark class fields as `$derived`.

> !LEGACY
> In Svelte 4, you could use reactive statements for this.
>
> ```svelte
> <script>
> let count = 0;
> $: doubled = count * 2;
> </script>
>
> <button on:click={() => count++}>
> {doubled}
> </button>
>
> <p>{count} doubled is {doubled}</p>
> ```
>
> This only worked at the top level of a component.

## `$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==)):
Expand All @@ -86,3 +117,28 @@ To run _side-effects_ when the component is mounted to the DOM, and when values
```

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.

> !LEGACY
> In Svelte 4, you could use reactive statements for this.
>
> ```svelte
> <script>
> let size = 50;
> let color = '#ff3e00';
>
> let canvas;
>
> $: {
> 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" />
> ```
>
> This only worked at the top level of a component.
12 changes: 6 additions & 6 deletions apps/svelte.dev/src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@

<!-- add inline style and blocking script to prevent content flash/jump -->
<style>
.ts-version {
.js-version {
display: none;
}
.prefers-ts .js-version {
display: none;
}
.prefers-ts .ts-version {
.prefers-js .js-version {
display: block;
}
.no-js .ts-toggle {
.prefers-js .ts-version {
display: none;
}
.hide-legacy-notes blockquote.legacy {
display: none;
}
</style>
Expand Down
2 changes: 1 addition & 1 deletion apps/svelte.dev/src/routes/docs/[...path]/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
.container {
--sidebar-menu-width: 28rem;
--sidebar-width: var(--sidebar-menu-width);
--ts-toggle-height: 4.2rem;
--legacy-toggle-height: 4.2rem;

display: flex;
flex-direction: column;
Expand Down
18 changes: 8 additions & 10 deletions packages/site-kit/src/lib/docs/DocsContents.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<script lang="ts">
import { page } from '$app/stores';
import TSToggle from './TSToggle.svelte';
import LegacyToggle from './LegacyToggle.svelte';
import type { Document } from '../types';

interface Props {
contents: Document[];
show_ts_toggle?: boolean;
}

let { contents, show_ts_toggle = false }: Props = $props();
let { contents }: Props = $props();
</script>

<nav aria-label="Docs">
Expand Down Expand Up @@ -38,11 +38,9 @@
</ul>
</nav>

{#if show_ts_toggle}
<div class="ts-toggle">
<TSToggle />
</div>
{/if}
<div class="legacy-toggle">
<LegacyToggle />
</div>

<style>
nav {
Expand Down Expand Up @@ -108,7 +106,7 @@
margin: 0;
}

.ts-toggle {
.legacy-toggle {
position: fixed;
width: var(--sidebar-width);
bottom: var(--sk-banner-bottom-height);
Expand Down Expand Up @@ -151,7 +149,7 @@
font-weight: 400;
}

.ts-toggle {
.legacy-toggle {
display: none;
}
}
Expand All @@ -167,7 +165,7 @@
}

nav {
max-height: calc(100vh - var(--ts-toggle-height) - var(--sk-nav-height));
max-height: calc(100vh - var(--legacy-toggle-height) - var(--sk-nav-height));
overflow-x: hidden;
overflow-y: auto;
}
Expand Down
38 changes: 38 additions & 0 deletions packages/site-kit/src/lib/docs/LegacyToggle.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script lang="ts">
import { persisted } from 'svelte-persisted-store';

const show = persisted('svelte:show-legacy-notes', true);

$effect(() => {
document.body.classList.toggle('hide-legacy-notes', !$show);
});
</script>

<label class="legacy-toggle" class:unchecked={!$show}>
<input type="checkbox" bind:checked={$show} />
<span>Show Legacy Docs</span>
</label>

<style>
.legacy-toggle {
position: relative;
display: flex;
gap: 0.5em;
align-items: center;
height: var(--legacy-toggle-height);
z-index: 2;
padding: 0 var(--sk-page-padding-side);
margin: 0 auto;
&.unchecked {
opacity: 0.8;
}
}

@media (min-width: 832px) {
.legacy-toggle {
padding: 0 0 0 2rem;
width: var(--sidebar-menu-width);
margin: 0 0 0 auto;
}
}
</style>
48 changes: 0 additions & 48 deletions packages/site-kit/src/lib/docs/TSToggle.svelte

This file was deleted.

2 changes: 1 addition & 1 deletion packages/site-kit/src/lib/docs/TsJsSelect.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

if (browser) {
prefers_ts.subscribe((ts) => {
document.body.classList.toggle('prefers-ts', ts);
document.body.classList.toggle('prefers-js', !ts);
});
}
</script>
Expand Down
2 changes: 1 addition & 1 deletion packages/site-kit/src/lib/docs/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { default as DocsContents } from './DocsContents.svelte';
export { default as DocsOnThisPage } from './DocsOnThisPage.svelte';
export { default as TSToggle } from './TSToggle.svelte';
export { default as LegacyToggle } from './LegacyToggle.svelte';
export { setupDocsHovers } from './hover';
5 changes: 5 additions & 0 deletions packages/site-kit/src/lib/markdown/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ const default_renderer: Partial<Renderer> = {
},

blockquote(quote) {
if (quote.startsWith('<p>!LEGACY')) {
quote = quote.replace('<p>!LEGACY', '<p>');
return '<blockquote class="legacy">\n' + quote + '</blockquote>\n';
}

return '<blockquote>\n' + quote + '</blockquote>\n';
},

Expand Down
9 changes: 7 additions & 2 deletions packages/site-kit/src/lib/styles/text.css
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@
margin-bottom: 0;
}

.text :where(blockquote.deprecated) {
.text :where(blockquote.deprecated, blockquote.legacy) {
--primary-hsl: var(--sk-text-warning-hsl);
--color: var(--primary-hsl);
}
Expand All @@ -333,10 +333,15 @@
content: 'Deprecated';
}

.text :where(blockquote.deprecated a) {
.text :where(blockquote.deprecated a),
.text :where(blockquote.legacy a) {
--color: var(--primary-hsl);
}

.text :where(blockquote.legacy)::before {
content: 'In Svelte 4 / Legacy mode';
}

.text :where(section a code) {
color: inherit;
}
Expand Down
Loading