Drawer
A slide-in panel anchored to any edge of the viewport. Drawers support titles, descriptions, footers, drag handles, snap points, and inset styling.
Playground
Experiment with different props in real-time.
Basic Usage
Import and use the Drawer component with bind:open for two-way binding. Provide a title and description for the header.
<script lang="ts">
import { Drawer, Button } from 'sv5ui';
let open = $state(false);
</script>
<Drawer bind:open title="Basic Drawer" description="This is a simple drawer example.">
<Button label="Open Drawer" onclick={() => (open = true)} />
{#snippet body()}
<p>This is the drawer body content.</p>
{/snippet}
</Drawer>Directions
Open the drawer from any edge using the direction prop.
<Drawer bind:open direction="bottom" title="Bottom Drawer">
<Button label="Bottom" onclick={() => (open = true)} />
{#snippet body()}
<p>Slides in from the bottom.</p>
{/snippet}
</Drawer>
<Drawer bind:open direction="left" title="Left Drawer">
<Button label="Left" onclick={() => (open = true)} />
{#snippet body()}
<p>Slides in from the left.</p>
{/snippet}
</Drawer>
<Drawer bind:open direction="right" title="Right Drawer">
<Button label="Right" onclick={() => (open = true)} />
{#snippet body()}
<p>Slides in from the right.</p>
{/snippet}
</Drawer>
<Drawer bind:open direction="top" title="Top Drawer">
<Button label="Top" onclick={() => (open = true)} />
{#snippet body()}
<p>Slides in from the top.</p>
{/snippet}
</Drawer>Inset
Use the inset prop for rounded corners and padding from the viewport edges.
<Drawer bind:open inset title="Inset Drawer" description="Rounded corners with padding from edges.">
<Button label="Open Inset Drawer" onclick={() => (open = true)} />
{#snippet body()}
<p>This drawer has inset styling with rounded corners.</p>
{/snippet}
</Drawer>With Footer
Add action buttons in the footer snippet.
<Drawer bind:open title="Confirm Action" description="Are you sure you want to proceed?">
<Button label="Open Drawer" onclick={() => (open = true)} />
{#snippet body()}
<p>This action cannot be undone. Please review before confirming.</p>
{/snippet}
{#snippet footer()}
<div class="flex gap-2 justify-end">
<Button variant="outline" label="Cancel" onclick={() => (open = false)} />
<Button label="Confirm" onclick={() => (open = false)} />
</div>
{/snippet}
</Drawer>Without Handle
Hide the drag handle by setting handle={false}.
<Drawer bind:open handle={false} title="No Handle" description="This drawer has no drag handle.">
<Button label="Open Drawer" onclick={() => (open = true)} />
{#snippet body()}
<p>The drag handle is hidden.</p>
{/snippet}
</Drawer>Non-Dismissible
Prevent dismissal via overlay click or drag with dismissible={false}. Provide an explicit close action.
<Drawer bind:open dismissible={false} title="Non-Dismissible" description="You must use the button to close.">
<Button label="Open Drawer" onclick={() => (open = true)} />
{#snippet body()}
<p>This drawer cannot be dismissed by clicking the overlay or dragging.</p>
{/snippet}
{#snippet footer()}
<Button label="Close" onclick={() => (open = false)} class="w-full" />
{/snippet}
</Drawer>UI Slots
Use the ui prop to override classes on specific internal elements of the Drawer.
| Slot | Description |
|---|---|
overlay | Background overlay behind the drawer — controls opacity and backdrop |
content | Main drawer container — controls size, position, background, and rounding |
handle | Drag handle bar at the top — controls width, height, color |
header | Header area wrapping title and description — controls padding and layout |
container | Inner container inside content — controls scroll and overflow |
title | Title text element — controls font size, weight, color |
description | Description text below title — controls font size and opacity |
body | Main body content area — controls padding and spacing |
footer | Footer area for actions — controls padding, border, and layout |
Snippets
Use Svelte 5 snippets to customize specific parts of the Drawer.
| Snippet | Type | Description |
|---|---|---|
children | Snippet | Trigger element — clicking opens the drawer |
content | Snippet | Custom content replacing the entire default layout |
header | Snippet | Custom header section |
titleSlot | Snippet | Custom title content — overrides title prop |
descriptionSlot | Snippet | Custom description content — overrides description prop |
body | Snippet | Main body content area |
footer | Snippet | Footer area for action buttons |
Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | false | |
onOpenChange | (open: boolean) => void | - | |
direction | 'top' | 'right' | 'bottom' | 'left' | 'bottom' | |
inset | boolean | false | |
title | string | - | |
description | string | - | |
overlay | boolean | true | |
handle | boolean | true | |
dismissible | boolean | true | |
shouldScaleBackground | boolean | false | |
snapPoints | (number | string)[] | - | |
modal | boolean | true | |
nested | boolean | false | |
portal | boolean | true | |
class | string | - | |
ui | Record<Slot, Class> | - |