Drawer
A panel that slides in from the edge of the screen. Use it for forms, detail views, settings, and navigation.
Basic
vue
<template>
<VxDrawer v-model="show" title="Drawer" description="A basic drawer.">
<p>Content goes here.</p>
</VxDrawer>
</template>Direction
Drawers can slide in from any edge: right (default), left, top, or bottom.
vue
<template>
<VxDrawer v-model="show" title="Right" direction="right" />
<VxDrawer v-model="show" title="Left" direction="left" />
<VxDrawer v-model="show" title="Top" direction="top" />
<VxDrawer v-model="show" title="Bottom" direction="bottom" />
</template>Sizes
Five sizes available: sm, md (default), lg, xl, full.
vue
<template>
<VxDrawer size="sm" title="Small" />
<VxDrawer size="md" title="Medium" />
<VxDrawer size="lg" title="Large" />
<VxDrawer size="xl" title="XL" />
<VxDrawer size="full" title="Full" />
</template>Form Drawer
A common pattern: a form inside a drawer with save/cancel actions.
vue
<template>
<VxDrawer v-model="show" title="Edit Profile">
<form>
<input v-model="form.name" placeholder="Name" />
<input v-model="form.email" placeholder="Email" />
</form>
<template #footer>
<button @click="show = false">Cancel</button>
<button @click="save">Save</button>
</template>
</VxDrawer>
</template>Scrollable Content
When content overflows, the body scrolls while header and footer stay fixed.
vue
<template>
<VxDrawer v-model="show" title="Terms of Service">
<div>Long scrollable content...</div>
<template #footer>
<button @click="show = false">Decline</button>
<button @click="accept">Accept</button>
</template>
</VxDrawer>
</template>Custom Header
vue
<template>
<VxDrawer v-model="show">
<template #header>
<div class="custom-header">
<MyIcon />
<div>
<h3>Task Completed</h3>
<p>Review the details below</p>
</div>
</div>
</template>
<p>Content...</p>
</VxDrawer>
</template>No Footer
vue
<template>
<VxDrawer v-model="show" title="Notifications" :show-footer="false">
<NotificationList />
</VxDrawer>
</template>Persistent
The drawer shakes instead of closing when clicking the overlay or pressing Escape.
vue
<template>
<VxDrawer v-model="show" persistent title="Unsaved" />
</template>No Overlay
vue
<template>
<VxDrawer v-model="show" hide-overlay title="Side Panel" />
</template>Loading
vue
<template>
<VxDrawer v-model="show" :loading="isLoading" title="Loading" />
</template>Nested Drawers
Open a drawer from within another drawer. Each gets its own overlay and z-index.
vue
<template>
<VxDrawer v-model="outer" title="Settings" size="lg">
<SettingsList @open-detail="inner = true" />
</VxDrawer>
<VxDrawer v-model="inner" title="Detail" size="sm">
<DetailContent />
</VxDrawer>
</template>Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | boolean | false | Show/hide (v-model) |
title | string | '' | Header title |
description | string | '' | Header description |
direction | 'left' | 'right' | 'top' | 'bottom' | 'right' | Slide-in direction |
size | 'sm' | 'md' | 'lg' | 'xl' | 'full' | 'md' | Panel size |
closable | boolean | true | Show close button |
closeOnOverlay | boolean | true | Close on overlay click |
closeOnEsc | boolean | true | Close on Escape |
persistent | boolean | false | Shake on dismiss attempt |
hideOverlay | boolean | false | No backdrop |
loading | boolean | false | Loading overlay |
showFooter | boolean | true | Show footer area |
beforeClose | () => boolean | Promise<boolean> | — | Guard before close |
destroyOnClose | boolean | false | Destroy content on close |
teleportTo | string | 'body' | Teleport target |
Events
| Event | Description |
|---|---|
update:modelValue | Value changed |
close | Drawer closed |
opened | Enter transition finished |
closed | Leave transition finished |
Slots
| Slot | Description |
|---|---|
default | Body content |
header | Custom header (replaces title/description) |
footer | Custom footer buttons |
Exposed
| Method | Description |
|---|---|
close() | Programmatically close (respects beforeClose) |