Usage
Use a Button or any other component in the default slot of the Drawer.
Then, use the #content slot to add the content displayed when the Drawer is open.
<template>
<B24Drawer>
<B24Button label="Open" />
<template #content>
<Placeholder class="h-48 m-4" />
</template>
</B24Drawer>
</template>
You can also use the #header, #body and #footer slots to customize the Drawer's content.
Title
Use the title prop to set the title of the Drawer's header.
<template>
<B24Drawer title="Drawer with title">
<B24Button label="Open" />
<template #body>
<Placeholder class="h-48" />
</template>
</B24Drawer>
</template>
Description
Use the description prop to set the description of the Drawer's header.
<template>
<B24Drawer
title="Drawer with description"
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
>
<B24Button label="Open" />
<template #body>
<Placeholder class="h-48" />
</template>
</B24Drawer>
</template>
Direction
Use the direction prop to control the direction of the Drawer. Defaults to bottom.
<template>
<B24Drawer direction="right">
<B24Button label="Open" />
<template #content>
<Placeholder class="min-w-96 min-h-96 size-full m-4" />
</template>
</B24Drawer>
</template>
Inset
Use the inset prop to inset the Drawer from the edges.
<template>
<B24Drawer direction="right" inset>
<B24Button label="Open" />
<template #content>
<Placeholder class="min-w-96 min-h-96 size-full m-4" />
</template>
</B24Drawer>
</template>
Handle
Use the handle prop to control whether the Drawer has a handle or not. Defaults to true.
<template>
<B24Drawer :handle="false">
<B24Button label="Open" />
<template #content>
<Placeholder class="h-48 m-4" />
</template>
</B24Drawer>
</template>
Handle Only
Use the handle-only prop to only allow the Drawer to be dragged by the handle.
<template>
<B24Drawer handle-only>
<B24Button label="Open" />
<template #content>
<Placeholder class="h-48 m-4" />
</template>
</B24Drawer>
</template>
Overlay
Use the overlay prop to control whether the Drawer has an overlay or not. Defaults to true.
<template>
<B24Drawer :overlay="false">
<B24Button label="Open" />
<template #content>
<Placeholder class="h-48 m-4" />
</template>
</B24Drawer>
</template>
@todo add overlayBlur
Modal
Use the modal prop to control whether the Drawer blocks interaction with outside content. Defaults to true.
modal is set to false, the overlay is automatically disabled and outside content becomes interactive.<template>
<B24Drawer :modal="false">
<B24Button label="Open" />
<template #content>
<Placeholder class="h-48 m-4" />
</template>
</B24Drawer>
</template>
Dismissible
Use the dismissible prop to control whether the Drawer is dismissible when clicking outside of it or pressing escape. Defaults to true.
close:prevent event will be emitted when the user tries to close it.modal: false with dismissible: false to make the Drawer's background interactive without closing it.Scale Background
Use the should-scale-background prop to scale the background when the Drawer is open, creating a visual depth effect. You can set the set-background-color-on-scale prop to false to prevent changing the background color.
<template>
<B24Drawer should-scale-background set-background-color-on-scale>
<B24Button label="Open" />
<template #content>
<Placeholder class="h-48 m-4" />
</template>
</B24Drawer>
</template>
data-vaul-drawer-wrapper directive to a parent element of your app to make this work.@todo fix this bg-default<template>
<B24App>
<div class="bg-default" data-vaul-drawer-wrapper>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</B24App>
</template>
export default defineNuxtConfig({
app: {
rootAttrs: {
'data-vaul-drawer-wrapper': '',
'class': 'bg-default'
}
}
})
Examples
Control open state
You can control the open state by using the default-open prop or the v-model:open directive.
defineShortcuts, you can toggle the Drawer by pressing O.Responsive drawer
You can render a Modal component on desktop and a Drawer on mobile for example.
Nested drawers
You can nest drawers within each other by using the nested prop.
With footer slot
Use the #footer slot to add content after the Drawer's body.
With command palette
You can use a CommandPalette component inside the Drawer's content.
API
Props
Slots
Emits
Theme
export default defineAppConfig({
b24ui: {
drawer: {
slots: {
overlay: 'fixed inset-0',
content: 'fixed base-mode bg-(--ui-color-bg-content-primary) flex focus:outline-none ring ring-(--ui-color-divider-default)',
handle: 'shrink-0 !bg-(--ui-color-divider-default) transition-opacity',
container: 'w-full flex flex-col gap-4 p-4 overflow-y-auto',
header: '',
title: 'font-[family-name:var(--ui-font-family-primary)] text-(--b24ui-typography-label-color) font-(--ui-font-weight-medium) mb-0 text-[calc(var(--ui-font-size-2xl)+2px)]/(--ui-font-size-2xl)',
description: 'mt-1 text-(--b24ui-typography-description-color) text-(length:--ui-font-size-sm)',
body: 'flex-1',
footer: 'flex flex-col gap-1.5'
},
variants: {
overlayBlur: {
auto: {
overlay: 'motion-safe:backdrop-blur-[2px]'
},
on: {
overlay: 'backdrop-blur-[2px]'
},
off: {
overlay: ''
}
},
scrollbarThin: {
true: {
body: 'scrollbar-thin'
}
},
overlay: {
true: {
overlay: 'bg-[#003366]/20'
}
},
direction: {
top: {
content: 'mb-24 flex-col-reverse',
handle: 'mb-4'
},
right: {
content: 'flex-row',
handle: '!ml-4'
},
bottom: {
content: 'mt-24 flex-col',
handle: 'mt-4'
},
left: {
content: 'flex-row-reverse',
handle: '!mr-4'
}
},
inset: {
true: {
content: 'rounded-lg after:hidden overflow-hidden [--initial-transform:calc(100%+1.5rem)]'
}
},
snapPoints: {
true: ''
}
},
compoundVariants: [
{
direction: [
'top',
'bottom'
],
class: {
content: 'h-auto max-h-[96%]',
handle: '!w-12 !h-1.5 mx-auto'
}
},
{
direction: [
'top',
'bottom'
],
snapPoints: true,
class: {
content: 'h-full'
}
},
{
direction: [
'right',
'left'
],
class: {
content: 'w-auto max-w-[calc(100%-2rem)]',
handle: '!h-12 !w-1.5 mt-auto mb-auto'
}
},
{
direction: [
'right',
'left'
],
snapPoints: true,
class: {
content: 'w-full'
}
},
{
direction: 'top',
inset: true,
class: {
content: 'inset-x-4 top-4'
}
},
{
direction: 'top',
inset: false,
class: {
content: 'inset-x-0 top-0 rounded-b-lg'
}
},
{
direction: 'bottom',
inset: true,
class: {
content: 'inset-x-4 bottom-4'
}
},
{
direction: 'bottom',
inset: false,
class: {
content: 'inset-x-0 bottom-0 rounded-t-lg'
}
},
{
direction: 'left',
inset: true,
class: {
content: 'inset-y-4 left-4'
}
},
{
direction: 'left',
inset: false,
class: {
content: 'inset-y-0 left-0 rounded-r-lg'
}
},
{
direction: 'right',
inset: true,
class: {
content: 'inset-y-4 right-4'
}
},
{
direction: 'right',
inset: false,
class: {
content: 'inset-y-0 right-0 rounded-l-lg'
}
}
]
}
}
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite'
export default defineConfig({
plugins: [
vue(),
bitrix24UIPluginVite({
b24ui: {
drawer: {
slots: {
overlay: 'fixed inset-0',
content: 'fixed base-mode bg-(--ui-color-bg-content-primary) flex focus:outline-none ring ring-(--ui-color-divider-default)',
handle: 'shrink-0 !bg-(--ui-color-divider-default) transition-opacity',
container: 'w-full flex flex-col gap-4 p-4 overflow-y-auto',
header: '',
title: 'font-[family-name:var(--ui-font-family-primary)] text-(--b24ui-typography-label-color) font-(--ui-font-weight-medium) mb-0 text-[calc(var(--ui-font-size-2xl)+2px)]/(--ui-font-size-2xl)',
description: 'mt-1 text-(--b24ui-typography-description-color) text-(length:--ui-font-size-sm)',
body: 'flex-1',
footer: 'flex flex-col gap-1.5'
},
variants: {
overlayBlur: {
auto: {
overlay: 'motion-safe:backdrop-blur-[2px]'
},
on: {
overlay: 'backdrop-blur-[2px]'
},
off: {
overlay: ''
}
},
scrollbarThin: {
true: {
body: 'scrollbar-thin'
}
},
overlay: {
true: {
overlay: 'bg-[#003366]/20'
}
},
direction: {
top: {
content: 'mb-24 flex-col-reverse',
handle: 'mb-4'
},
right: {
content: 'flex-row',
handle: '!ml-4'
},
bottom: {
content: 'mt-24 flex-col',
handle: 'mt-4'
},
left: {
content: 'flex-row-reverse',
handle: '!mr-4'
}
},
inset: {
true: {
content: 'rounded-lg after:hidden overflow-hidden [--initial-transform:calc(100%+1.5rem)]'
}
},
snapPoints: {
true: ''
}
},
compoundVariants: [
{
direction: [
'top',
'bottom'
],
class: {
content: 'h-auto max-h-[96%]',
handle: '!w-12 !h-1.5 mx-auto'
}
},
{
direction: [
'top',
'bottom'
],
snapPoints: true,
class: {
content: 'h-full'
}
},
{
direction: [
'right',
'left'
],
class: {
content: 'w-auto max-w-[calc(100%-2rem)]',
handle: '!h-12 !w-1.5 mt-auto mb-auto'
}
},
{
direction: [
'right',
'left'
],
snapPoints: true,
class: {
content: 'w-full'
}
},
{
direction: 'top',
inset: true,
class: {
content: 'inset-x-4 top-4'
}
},
{
direction: 'top',
inset: false,
class: {
content: 'inset-x-0 top-0 rounded-b-lg'
}
},
{
direction: 'bottom',
inset: true,
class: {
content: 'inset-x-4 bottom-4'
}
},
{
direction: 'bottom',
inset: false,
class: {
content: 'inset-x-0 bottom-0 rounded-t-lg'
}
},
{
direction: 'left',
inset: true,
class: {
content: 'inset-y-4 left-4'
}
},
{
direction: 'left',
inset: false,
class: {
content: 'inset-y-0 left-0 rounded-r-lg'
}
},
{
direction: 'right',
inset: true,
class: {
content: 'inset-y-4 right-4'
}
},
{
direction: 'right',
inset: false,
class: {
content: 'inset-y-0 right-0 rounded-l-lg'
}
}
]
}
}
})
]
})