Skip to content
Merged
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,23 @@ class Todo {
}
```

<details class="legacy">
<summary>Legacy mode</summary>

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>
```

</details>

## `$derived`

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

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

<details class="legacy">
<summary>Legacy mode</summary>
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.

</details>

## `$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 +124,31 @@ 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.

<details class="legacy">
<summary>Legacy mode</summary>
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.

</details>
17 changes: 11 additions & 6 deletions apps/svelte.dev/src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,13 @@

<!-- 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;
}
</style>
Expand All @@ -48,5 +45,13 @@
</script>

<div style="height: 100%">%sveltekit.body%</div>

<script>
if (localStorage.getItem('svelte:show-legacy') !== 'false') {
for (const node of document.querySelectorAll('details.legacy')) {
node.open = true;
}
}
</script>
</body>
</html>
1 change: 0 additions & 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,6 @@
.container {
--sidebar-menu-width: 28rem;
--sidebar-width: var(--sidebar-menu-width);
--ts-toggle-height: 4.2rem;

display: flex;
flex-direction: column;
Expand Down
4 changes: 2 additions & 2 deletions apps/svelte.dev/src/routes/docs/[...path]/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script>
import { Icon } from '@sveltejs/site-kit/components';
import { copy_code_descendants, ts_js_select } from '@sveltejs/site-kit/actions';
import { copy_code_descendants, legacy_details, ts_js_select } from '@sveltejs/site-kit/actions';
import { DocsOnThisPage, setupDocsHovers } from '@sveltejs/site-kit/docs';

let { data } = $props();
Expand All @@ -19,7 +19,7 @@
<meta name="Description" content="{data.document.metadata.title} • Svelte documentation" />
</svelte:head>

<div class="text" id="docs-content" use:ts_js_select use:copy_code_descendants>
<div class="text" id="docs-content" use:ts_js_select use:copy_code_descendants use:legacy_details>
<a
class="edit"
href="https://github.com/sveltejs/svelte.dev/edit/main/apps/svelte.dev/content/{data.document
Expand Down
1 change: 1 addition & 0 deletions packages/site-kit/src/lib/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export { focus_outside } from './focus-outside';
export { focusable_children, trap } from './focus';
export { root_scroll } from './root-scroll';
export { ts_js_select } from './ts-js-select';
export { legacy_details } from './legacy-details';
63 changes: 63 additions & 0 deletions packages/site-kit/src/lib/actions/legacy-details.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { page } from '$app/stores';
import { persisted } from 'svelte-persisted-store';
import { get } from 'svelte/store';

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

export function legacy_details(node: HTMLElement) {
function update() {
let scroll_parent: HTMLElement | null = node;

while ((scroll_parent = scroll_parent.parentElement)) {
if (/^(scroll|auto)$/.test(getComputedStyle(scroll_parent).overflowY)) {
break;
}
}

const details = node.querySelectorAll('details.legacy') as NodeListOf<HTMLDetailsElement>;
const show = get(show_legacy);

/** Whether the toggle was initiated by user action or `element.open = !element.open` */
let secondary = false;

// Add a select to each code block
for (const detail of details) {
detail.open = show;

detail.addEventListener('toggle', (e) => {
if (secondary) return;
secondary = true;

show_legacy.set(detail.open);

const top = detail.getBoundingClientRect().top;

for (const other of details) {
if (other !== detail) {
other.open = detail.open;
}
}

const delta = detail.getBoundingClientRect().top - top;

if (delta !== 0) {
// whichever element the user interacted with should stay in the same position
(scroll_parent ?? document.body).scrollBy(0, delta);
}

setTimeout(() => {
secondary = false;
});
});
}
}

// Page changed. Update again
const unsubscribe = page.subscribe(update);

return {
destroy() {
unsubscribe();
}
};
}
27 changes: 2 additions & 25 deletions packages/site-kit/src/lib/docs/DocsContents.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
<script lang="ts">
import { page } from '$app/stores';
import TSToggle from './TSToggle.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,12 +37,6 @@
</ul>
</nav>

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

<style>
nav {
top: 0;
Expand Down Expand Up @@ -108,18 +101,6 @@
margin: 0;
}

.ts-toggle {
position: fixed;
width: var(--sidebar-width);
bottom: var(--sk-banner-bottom-height);
left: 0;
z-index: 1;
margin-right: 0;
border-top: 1px solid var(--sk-back-4);
border-right: 1px solid var(--sk-back-5);
background-color: var(--sk-back-3);
}

@media (max-width: 831px) {
.sidebar {
padding: 1rem;
Expand Down Expand Up @@ -150,10 +131,6 @@
color: var(--sk-theme-1) !important;
font-weight: 400;
}

.ts-toggle {
display: none;
}
}

@media (min-width: 832px) {
Expand All @@ -167,7 +144,7 @@
}

nav {
max-height: calc(100vh - var(--ts-toggle-height) - var(--sk-nav-height));
max-height: calc(100vh - var(--sk-nav-height));
overflow-x: hidden;
overflow-y: auto;
}
Expand Down
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
1 change: 0 additions & 1 deletion packages/site-kit/src/lib/docs/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export { default as DocsContents } from './DocsContents.svelte';
export { default as DocsOnThisPage } from './DocsOnThisPage.svelte';
export { default as TSToggle } from './TSToggle.svelte';
export { setupDocsHovers } from './hover';
31 changes: 31 additions & 0 deletions packages/site-kit/src/lib/styles/text.css
Original file line number Diff line number Diff line change
Expand Up @@ -344,3 +344,34 @@
.text :where(ul ul) {
margin-bottom: 0;
}

details.legacy {
background-color: hsla(var(--sk-text-warning-hsl), 0.02);
border-radius: var(--sk-border-radius);
padding: 1rem;
margin: 1rem 0;

& > summary {
color: hsl(var(--sk-text-warning-hsl));
font-size: 1.4rem;
font-weight: 600;
cursor: pointer;

&::after {
content: 'show all';
float: right;
}
}

&[open] > summary {
margin-bottom: 1.4rem;

&::after {
content: 'hide all';
}
}

> :last-child {
margin-bottom: 0;
}
}
Loading