-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
Describe the bug
In the docs, the only mention of snippets-slots interop is:
In Svelte 4, content can be passed to components using slots. Svelte 5 replaces them with snippets which are more powerful and flexible, and as such slots are deprecated in Svelte 5.
They continue to work, however, and you can mix and match snippets and slots in your components.
But it doesn't say exactly what that means. It is intuitive that you can use old components with slots from new snippet-based components, but not the other way around, and that slot props are passed using destructuring, as they are named, but I think this should be documented a bit.
<!-- Child.svelte -->
<slot name="named" />
<br>
<slot />
<!-- Parent.svelte -->
<Child>
{#snippet named()}
Named
{/snippet}
Default
</Child><!-- Child.svelte -->
<script>
let value = 0
</script>
<slot name="named" {value} />
<br>
<slot {value} />
<br>
<button on:click={() => value++}>Increment</button>
<!-- Parent.svelte -->
<Child>
{#snippet named({ value })}
Named: {value}
{/snippet}
{#snippet children({ value })}
Default with value: {value}
{/snippet}
</Child>But the other way around doesn't work (except for default slots and without props), as it doesn't make sense to write Svelte 4 code using Svelte 5 code, but I think it can happen if upgrading to Svelte 5 libraries in a codebase that's not fully migrated:
<!-- Child.svelte -->
<script>
let { children, named } = $props()
</script>
{@render children?.()}
<br>
{@render named?.()}
<!-- Parent.svelte -->
<Child>
<!-- This doesn't get rendered -->
<svelte:fragment slot="named">
Named
</svelte:fragment>
Default
</Child><!-- Child.svelte -->
<script>
let { children, named } = $props()
</script>
{@render children?.({ value: 123 })}
<!-- Parent.svelte -->
<!-- invalid_default_snippet Cannot use `{@render children(...)}` if the parent component uses `let:` directives. Consider using a named snippet instead in New.svelte in App.svelte -->
<Child let:value>
Value: {value}
</Child>