Skip to main content

Overview

The Drawer component provides a slide-in panel from screen edges, ideal for navigation menus, filters, or additional content. Built on vaul-vue for smooth mobile-friendly interactions.

Basic Usage

<template>
  <UDrawer v-model:open="isOpen" title="Drawer Title" description="Drawer description">
    <template #default>
      <UButton>Open Drawer</UButton>
    </template>
    <template #body>
      <p>Drawer content goes here</p>
    </template>
  </UDrawer>
</template>

<script setup>
const isOpen = ref(false)
</script>

Props

title
string
The title of the drawer displayed in the header.
description
string
The description text displayed below the title.
direction
'top' | 'bottom' | 'left' | 'right'
default:"'bottom'"
The direction from which the drawer slides in.
inset
boolean
default:"false"
Whether to inset the drawer from the edges.
overlay
boolean
default:"true"
Render an overlay behind the drawer.
handle
boolean
default:"true"
Render a drag handle on the drawer.
portal
boolean | string | HTMLElement
default:"true"
Render the drawer in a portal.
nested
boolean
default:"false"
Whether the drawer is nested in another drawer.
dismissible
boolean
default:"true"
When false, the drawer will not close when clicking outside or pressing escape.
open
boolean
Controls the open state of the drawer (v-model:open).
defaultOpen
boolean
The default open state when uncontrolled.
modal
boolean
default:"true"
When true, interaction outside the drawer will be disabled.
shouldScaleBackground
boolean
Whether to scale the background when the drawer opens.
snapPoints
(number | string)[]
Array of snap points that the drawer can snap to.
activeSnapPoint
number | string | null
The currently active snap point.
closeThreshold
number
The threshold for closing the drawer on swipe.
scrollLockTimeout
number
Timeout for scroll lock in milliseconds.
fixed
boolean
Whether the drawer uses fixed positioning.
handleOnly
boolean
When true, only the handle can be used to drag the drawer.
noBodyStyles
boolean
Prevent default body styles from being applied.
preventScrollRestoration
boolean
Prevent scroll restoration when drawer closes.
as
any
default:"'div'"
The element or component this component should render as.
content
DialogContentProps
Additional props passed to the drawer content element.
class
any
CSS class for styling the trigger element.
ui
object
Theme customization object for component slots.

Events

update:open
(open: boolean) => void
Emitted when the open state changes.
update:activeSnapPoint
(snapPoint: number | string | null) => void
Emitted when the active snap point changes.
close:prevent
() => void
Emitted when a close attempt is prevented (when dismissible is false).
drag
(event: PointerEvent, percentageDragged: number) => void
Emitted during drag interactions.
release
(event: PointerEvent, open: boolean) => void
Emitted when the drawer is released after dragging.

Slots

default
{}
The trigger element for opening the drawer.
content
{}
Complete control over the drawer content, replacing the default structure.
header
{}
Customizes the header section of the drawer.
title
{}
Customizes the title text.
description
{}
Customizes the description text.
body
{}
The main content area of the drawer.
Footer section for actions or additional content.

Examples

Drawer from Different Directions

<template>
  <UDrawer direction="left" v-model:open="isOpen" title="Left Drawer">
    <template #default>
      <UButton>Open from Left</UButton>
    </template>
    <template #body>
      <p>This drawer slides in from the left.</p>
    </template>
  </UDrawer>
</template>

With Snap Points

<template>
  <UDrawer 
    v-model:open="isOpen" 
    :snap-points="[0.5, 1]"
    v-model:activeSnapPoint="activeSnap"
    title="Snappable Drawer"
  >
    <template #default>
      <UButton>Open Snappable Drawer</UButton>
    </template>
    <template #body>
      <p>This drawer can snap to 50% or 100% height.</p>
    </template>
  </UDrawer>
</template>

<script setup>
const isOpen = ref(false)
const activeSnap = ref(0.5)
</script>

Nested Drawers

<template>
  <UDrawer v-model:open="outerOpen" title="Outer Drawer">
    <template #default>
      <UButton>Open Outer Drawer</UButton>
    </template>
    <template #body>
      <p>Outer drawer content</p>
      <UDrawer nested v-model:open="innerOpen" title="Inner Drawer">
        <template #default>
          <UButton>Open Inner Drawer</UButton>
        </template>
        <template #body>
          <p>Nested drawer content</p>
        </template>
      </UDrawer>
    </template>
  </UDrawer>
</template>

<script setup>
const outerOpen = ref(false)
const innerOpen = ref(false)
</script>

Without Handle

<template>
  <UDrawer v-model:open="isOpen" :handle="false" title="No Handle">
    <template #default>
      <UButton>Open Drawer</UButton>
    </template>
    <template #body>
      <p>This drawer has no drag handle.</p>
    </template>
    <template #footer>
      <UButton @click="isOpen = false">Close</UButton>
    </template>
  </UDrawer>
</template>
  • Modal - For centered dialog overlays
  • Sheet - Alternative drawer implementation
  • Drawer - vaul-vue documentation

Build docs developers (and LLMs) love