Skip to content

Commit 6bba70a

Browse files
Docs (#9449)
* rename file * add snippet docs * add note on deprecation * they're not attributes * event docs * prettier * remove unnecessary div * Apply suggestions from code review Co-authored-by: Simon H <[email protected]> * make example less confusing * note breaking props.children change --------- Co-authored-by: Rich Harris <[email protected]> Co-authored-by: Simon H <[email protected]>
1 parent e90ded6 commit 6bba70a

File tree

7 files changed

+432
-2
lines changed

7 files changed

+432
-2
lines changed

.prettierrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
"useTabs": false,
1818
"tabWidth": 2
1919
}
20+
},
21+
{
22+
"files": ["sites/svelte-5-preview/src/routes/docs/content/**/*.md"],
23+
"options": {
24+
"printWidth": 60
25+
}
2026
}
2127
]
2228
}

sites/svelte-5-preview/src/routes/docs/content/01-api/02-runes.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,10 @@ In rare cases, you may need to run code _before_ the DOM updates. For this we ca
128128
messages;
129129
130130
// autoscroll when new messages are added
131-
if (div.offsetHeight + div.scrollTop > div.scrollHeight - 20) {
131+
if (
132+
div.offsetHeight + div.scrollTop >
133+
div.scrollHeight - 20
134+
) {
132135
tick().then(() => {
133136
div.scrollTo(0, div.scrollHeight);
134137
});
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
---
2+
title: Snippets
3+
---
4+
5+
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=)...
6+
7+
```svelte
8+
{#each images as image}
9+
{#if image.href}
10+
<a href={image.href}>
11+
<figure>
12+
<img
13+
src={image.src}
14+
alt={image.caption}
15+
width={image.width}
16+
height={image.height}
17+
/>
18+
<figcaption>{image.caption}</figcaption>
19+
</figure>
20+
</a>
21+
{:else}
22+
<figure>
23+
<img
24+
src={image.src}
25+
alt={image.caption}
26+
width={image.width}
27+
height={image.height}
28+
/>
29+
<figcaption>{image.caption}</figcaption>
30+
</figure>
31+
{/if}
32+
{/each}
33+
```
34+
35+
...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=):
36+
37+
```diff
38+
+{#snippet figure(image)}
39+
<figure>
40+
<img
41+
src={image.src}
42+
alt={image.caption}
43+
width={image.width}
44+
height={image.height}
45+
/>
46+
<figcaption>{image.caption}</figcaption>
47+
</figure>
48+
+{/snippet}
49+
50+
{#each images as image}
51+
{#if image.href}
52+
<a href={image.href}>
53+
+ {@render figure(image)}
54+
</a>
55+
{:else}
56+
+ {@render figure(image)}
57+
{/if}
58+
{/each}
59+
```
60+
61+
A snippet can have at most one parameter. You can destructure it, just like a function argument ([demo](/#H4sIAAAAAAAAE5VTYW-bMBD9KyeiKYlEY4jWfSAk2n5H6QcXDmwVbMs2SzuL_z6DTRqp2rQJ2Ycfd_ced2eXtLxHkxRPLhF0wKRIfiiVpIl9V_PB_MTeoj8bOep6RkpTa67spRKV7dECH2iHBs7wNCOVdcFU1ui6gC2zVpmCEMVrMw4HxaSVhnzLMnLMsm26Ol95Y1kBHr9BDHnHbAHHO6ymynIpfF7LuAncwKgBCj0Xrx_5mMb2jh3f6KB6PNRy2AaXKf1fuY__KPfxj3KlQGikL5aQdpUxm-dTJUryUVdRsvwSqEviX2fIbYzgSvmCt7wbNe4ceMUpRIoUFkkpBBkw7ZfMZXC-BLKSDx3Q3p5djJrA-SR-X4K9DdHT6u-jo-flFlKSO3ThIDcSR6LIKUhGWrN1QGhs16LLbXgbjoe5U1PkozCfzu7uy2WtpfuuUTSo1_9ffPZrJKGLoyuwNxjBv0Q4wmdSR2aFi9jS2Pc-FIrlEKeilcI-GP4LfVtxOM1gyO1XSLp6vtD6tdNyFE0BV8YtngKuaNNw0RWQx_jKDlR33M9E5h-PQhZxfxEt6gIaLdWDYbSR191RvcFXv_LMb7p7obssXZ5Dvt_f9HgzdzZKibOZZ9mXmHkdTTpaefqsd4OIay4_hksd_I0fZMNbjk1SWD3i9Dz9BpdEPu8sBAAA)):
62+
63+
```svelte
64+
{#snippet figure({ src, caption, width, height })}
65+
<figure>
66+
<img alt={caption} {src} {width} {height} />
67+
<figcaption>{caption}</figcaption>
68+
</figure>
69+
{/snippet}
70+
```
71+
72+
## Snippet scope
73+
74+
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=))...
75+
76+
```svelte
77+
<script>
78+
let { message = `it's great to see you!` } = $props();
79+
</script>
80+
81+
{#snippet hello(name)}
82+
<p>hello {name}! {message}!</p>
83+
{/snippet}
84+
85+
{@render hello('alice')}
86+
{@render hello('bob')}
87+
```
88+
89+
...and they are 'visible' to everything in the same lexical scope (i.e. siblings, and children of those siblings):
90+
91+
```svelte
92+
<div>
93+
{#snippet x()}
94+
{#snippet y()}...{/snippet}
95+
96+
<!-- this is fine -->
97+
{@render y()}
98+
{/snippet}
99+
100+
<!-- this will error, as `y` is not in scope -->
101+
{@render y()}
102+
</div>
103+
104+
<!-- this will also error, as `x` is not in scope -->
105+
{@render x()}
106+
```
107+
108+
Snippets can reference themselves and each other ([demo](/#H4sIAAAAAAAAE2WPTQqDMBCFrxLiRqH1Zysi7TlqF1YnENBJSGJLCYGeo5tesUeosfYH3c2bee_jjaWMd6BpfrAU6x5oTvdS0g01V-mFPkNnYNRaDKrxGxto5FKCIaeu1kYwFkauwsoUWtZYPh_3W5FMY4U2mb3egL9kIwY0rbhgiO-sDTgjSEqSTvIDs-jiOP7i_MHuFGAL6p9BtiSbOTl0GtzCuihqE87cqtyam6WRGz_vRcsZh5bmRg3gju4Fptq_kzQBAAA=)):
109+
110+
```svelte
111+
{#snippet blastoff()}
112+
<span>🚀</span>
113+
{/snippet}
114+
115+
{#snippet countdown(n)}
116+
{#if n > 0}
117+
<span>{n}...</span>
118+
{@render countdown(n - 1)}
119+
{:else}
120+
{@render blastoff()}
121+
{/if}
122+
{/snippet}
123+
124+
{@render countdown(10)}
125+
```
126+
127+
## Passing snippets to components
128+
129+
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=)):
130+
131+
```svelte
132+
<script>
133+
import Table from './Table.svelte';
134+
135+
const fruits = [
136+
{ name: 'apples', qty: 5, price: 2 },
137+
{ name: 'bananas', qty: 10, price: 1 },
138+
{ name: 'cherries', qty: 20, price: 0.5 }
139+
];
140+
</script>
141+
142+
{#snippet header()}
143+
<th>fruit</th>
144+
<th>qty</th>
145+
<th>price</th>
146+
<th>total</th>
147+
{/snippet}
148+
149+
{#snippet row(d)}
150+
<td>{d.name}</td>
151+
<td>{d.qty}</td>
152+
<td>{d.price}</td>
153+
<td>{d.qty * d.price}</td>
154+
{/snippet}
155+
156+
<Table data={fruits} {header} {row} />
157+
```
158+
159+
As an authoring convenience, snippets declare 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=)):
160+
161+
```svelte
162+
<!-- this is semantically the same as the above -->
163+
<Table data={fruits}>
164+
{#snippet header()}
165+
<th>fruit</th>
166+
<th>qty</th>
167+
<th>price</th>
168+
<th>total</th>
169+
{/snippet}
170+
171+
{#snippet row(d)}
172+
<td>{d.name}</td>
173+
<td>{d.qty}</td>
174+
<td>{d.price}</td>
175+
<td>{d.qty * d.price}</td>
176+
{/snippet}
177+
</Table>
178+
```
179+
180+
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=)):
181+
182+
```diff
183+
<Table data={fruits}>
184+
- {#snippet header()}
185+
- <th>fruit</th>
186+
- <th>qty</th>
187+
- <th>price</th>
188+
- <th>total</th>
189+
- {/snippet}
190+
+ <th>fruit</th>
191+
+ <th>qty</th>
192+
+ <th>price</th>
193+
+ <th>total</th>
194+
195+
<!-- ... -->
196+
</Table>
197+
```
198+
199+
```diff
200+
<script>
201+
- let { data, header, row } = $props();
202+
+ let { data, children, row } = $props();
203+
</script>
204+
205+
<table>
206+
- {#if header}
207+
+ {#if children}
208+
<thead>
209+
- <tr>{@render header()}</tr>
210+
+ <tr>{@render children()}</tr>
211+
</thead>
212+
{/if}
213+
214+
<!-- ... -->
215+
</table>
216+
```
217+
218+
> 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
219+
220+
## Snippets and slots
221+
222+
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.
223+
224+
They continue to work, however, and you can mix and match snippets and slots in your components.
225+
226+
## Typing snippets
227+
228+
Right now, it's not possible to add types for snippets and their parameters. This is something we hope to address before we ship Svelte 5.

0 commit comments

Comments
 (0)