Snippets allow us to reuse content within a component, without extracting it out into a separate file.

We can create a snippet using the {#snippet snippet(params)}...{/snippet} syntax, but it doesn’t render until we render it using {@render snippet(params)}.

ex.

	<tbody>
		{#snippet monkey(emoji, description)}
			<tr>
				<td>{emoji}</td>
				<td>{description}</td>
				<td>\u{emoji.charCodeAt(0).toString(16)}\u{emoji.charCodeAt(1).toString(16)}</td>
				<td>&amp#{emoji.codePointAt(0)}</td>
			</tr>
		{/snippet}
		{@render monkey('🙈', 'see no evil')}
		{@render monkey('🙉', 'hear no evil')}
		{@render monkey('🙊', 'speak no evil')}
	</tbody>

As we can see from the example, it’s also possible to pass data into the snippet. Snippets can have zero or more parameters. Snippets can be declared anywhere in your component, but are only visible to render tags in the same ‘scope’ or child scope, like functions.

Passing snippets to components

Since snippets are just values, like functions, they can be passed to components as props. You can declare a snippet inside of some parent component and pass it down as props to a child component, where it actually gets rendered.

ex. inside App.svelte

<FilteredList
	data={colors}
	field="name"
	{header}
	{row}
></FilteredList>
 
{#snippet header()}
	<header>
		<span class="color"></span>
		<span class="name">name</span>
		<span class="hex">hex</span>
		<span class="rgb">rgb</span>
		<span class="hsl">hsl</span>
	</header>
{/snippet}
 
{#snippet row(d)}
	<div class="row">
		<span class="color" style="background-color: {d.hex}"></span>
		<span class="name">{d.name}</span>
		<span class="hex">{d.hex}</span>
		<span class="rgb">{d.rgb}</span>
		<span class="hsl">{d.hsl}</span>
	</div>
{/snippet}

and inside FilteredList.svelte

 
<script>
	let { data, field, header, row } = $props();
    // other stuff...
</script>
 
<div class="list">
	<label>
		Filter: <input bind:value={search} />
	</label>
 
	<div class="header">
		{@render header()}
	</div>
	<div class="content">
		{#each filtered as d}
			{@render row(d)}
		{/each}
	</div>
</div>

Implicit props

What we did in that previous example was explicitly telling the child component that the snippets were the properties assigned to it by the parent. However, we could do something else too - snippets declared directly inside the components become props on those components. This is what is meant by the snippets being implicit props.
So, as an example, we can move the header and row snippets inside <FilteredList>:

<FilteredList
	data={colors}
	field="name"
>
    {#snippet header()}
        <header>
            <span class="color"></span>
            <span class="name">name</span>
            <span class="hex">hex</span>
            <span class="rgb">rgb</span>
            <span class="hsl">hsl</span>
        </header>
    {/snippet}
 
    {#snippet row(d)}
        <div class="row">
            <span class="color" style="background-color: {d.hex}"></span>
            <span class="name">{d.name}</span>
            <span class="hex">{d.hex}</span>
            <span class="rgb">{d.rgb}</span>
            <span class="hsl">{d.hsl}</span>
        </div>
    {/snippet}
</FilteredList>

Any content inside a component that is not part of a declared snippet becomes a special children snippet. Since header has no parameters here, we could turn it into children by removing the block tags altogether:

<FilteredList
	data={colors}
	field="name"
>
    <header>
        <span class="color"></span>
        <span class="name">name</span>
        <span class="hex">hex</span>
        <span class="rgb">rgb</span>
        <span class="hsl">hsl</span>
    </header>
    <!-- other stuff... -->
</FilteredList>

and then, we would have to rename that prop to children in FilteredList.svelte:

<script lang="ts">
    let { data, field, children, row } = $props();
    // ...
</script>
<!-- other stuff ...-->
<div class="header">
    {@render children()}
</div>

Typing snippets

Snippets implement the Snippet interface imported from '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>