Overlay

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.

SlotDescription
overlayBackground overlay behind the drawer — controls opacity and backdrop
contentMain drawer container — controls size, position, background, and rounding
handleDrag handle bar at the top — controls width, height, color
headerHeader area wrapping title and description — controls padding and layout
containerInner container inside content — controls scroll and overflow
titleTitle text element — controls font size, weight, color
descriptionDescription text below title — controls font size and opacity
bodyMain body content area — controls padding and spacing
footerFooter area for actions — controls padding, border, and layout

Snippets

Use Svelte 5 snippets to customize specific parts of the Drawer.

SnippetTypeDescription
childrenSnippetTrigger element — clicking opens the drawer
contentSnippetCustom content replacing the entire default layout
headerSnippetCustom header section
titleSlotSnippetCustom title content — overrides title prop
descriptionSlotSnippetCustom description content — overrides description prop
bodySnippetMain body content area
footerSnippetFooter area for action buttons

Props

PropTypeDefault
openbooleanfalse
onOpenChange(open: boolean) => void-
direction'top' | 'right' | 'bottom' | 'left''bottom'
insetbooleanfalse
titlestring-
descriptionstring-
overlaybooleantrue
handlebooleantrue
dismissiblebooleantrue
shouldScaleBackgroundbooleanfalse
snapPoints(number | string)[]-
modalbooleantrue
nestedbooleanfalse
portalbooleantrue
classstring-
uiRecord<Slot, Class>-