Named Snippet Props

+15 Mana ✨

Components often need more than just children. Named snippets let you pass multiple content blocks.

The Pattern

svelte
<!-- Card.svelte -->
<script>
  let { header, children, footer } = $props();
</script>

<div class="card">
  {#if header}
    <div class="card-header">
      {@render header()}
    </div>
  {/if}
  
  <div class="card-body">
    {@render children?.()}
  </div>
  
  {#if footer}
    <div class="card-footer">
      {@render footer()}
    </div>
  {/if}
</div>

Passing Named Snippets

svelte
<Card>
  {#snippet header()}
    <h2>Card Title</h2>
    <span class="badge">New</span>
  {/snippet}
  
  <p>This is the main content.</p>
  <p>It can have multiple elements.</p>
  
  {#snippet footer()}
    <button>Cancel</button>
    <button>Save</button>
  {/snippet}
</Card>

Notice:

  • Named snippets go inside the component tags
  • Non-snippet content becomes children
  • Order doesn't matter — named snippets are matched by name

Explicit children Snippet

You can also define children explicitly:

svelte
<Card>
  {#snippet header()}
    <h2>Title</h2>
  {/snippet}
  
  {#snippet children()}
    <p>Explicit body content</p>
  {/snippet}
  
  {#snippet footer()}
    <button>OK</button>
  {/snippet}
</Card>

Real-World: Table Component

svelte
<!-- DataTable.svelte -->
<script>
  let { data, header, row, empty } = $props();
</script>

<table>
  <thead>
    {@render header()}
  </thead>
  <tbody>
    {#if data.length === 0}
      <tr>
        <td colspan="100">
          {#if empty}
            {@render empty()}
          {:else}
            No data available
          {/if}
        </td>
      </tr>
    {:else}
      {#each data as item, index}
        {@render row(item, index)}
      {/each}
    {/if}
  </tbody>
</table>
svelte
<!-- Usage -->
<DataTable data={users}>
  {#snippet header()}
    <tr>
      <th>Name</th>
      <th>Email</th>
      <th>Actions</th>
    </tr>
  {/snippet}
  
  {#snippet row(user, index)}
    <tr class:even={index % 2 === 0}>
      <td>{user.name}</td>
      <td>{user.email}</td>
      <td>
        <button onclick={() => edit(user)}>Edit</button>
      </td>
    </tr>
  {/snippet}
  
  {#snippet empty()}
    <div class="empty-state">
      <img src="/empty.svg" alt="" />
      <p>No users found</p>
      <button onclick={addUser}>Add First User</button>
    </div>
  {/snippet}
</DataTable>
✓ Completed