Drawer
Reveal focused content from any viewport edge and dismiss it with a directional swipe.
Usage
Bottom
Open a modal surface from the bottom edge and dismiss it by dragging the handle downward.
Open a modal surface from the bottom edge and dismiss it by dragging the handle downward.
<!-- Drawer / Bottom -->
<script setup lang="ts">
import { DrawerRoot, DrawerTrigger, DrawerOverlay, DrawerContent, DrawerHandle, DrawerTitle, DrawerDescription, DrawerClose } from '@sectile/vue/drawer'
</script>
<template>
<DrawerRoot>
<DrawerTrigger>Open filters</DrawerTrigger>
<DrawerOverlay class="drawer-overlay" />
<DrawerContent class="drawer-content">
<DrawerHandle class="drawer-handle" />
<DrawerTitle>Filters</DrawerTitle>
<DrawerDescription>Refine the deployment list.</DrawerDescription>
<DrawerClose>Apply filters</DrawerClose>
</DrawerContent>
</DrawerRoot>
</template>Side
Open the same drawer contract from a horizontal viewport edge.
Open the same drawer contract from a horizontal viewport edge.
<!-- Drawer / Side -->
<script setup lang="ts">
import { DrawerRoot, DrawerTrigger, DrawerOverlay, DrawerContent, DrawerHandle, DrawerTitle, DrawerDescription, DrawerClose } from '@sectile/vue/drawer'
</script>
<template>
<DrawerRoot side="right">
<DrawerTrigger>Open inspector</DrawerTrigger>
<DrawerOverlay class="drawer-overlay" />
<DrawerContent class="drawer-content drawer-content-side">
<DrawerHandle class="drawer-handle" />
<DrawerTitle>Inspector</DrawerTitle>
<DrawerDescription>Review the selected deployment.</DrawerDescription>
<DrawerClose>Close</DrawerClose>
</DrawerContent>
</DrawerRoot>
</template>Controlled
Let the parent own the current value and apply accepted changes back to the component.
Let the parent own the current value and apply accepted changes back to the component.
<!-- Drawer / Controlled -->
<script setup lang="ts">
import { DrawerRoot, DrawerTrigger, DrawerOverlay, DrawerContent, DrawerHandle, DrawerTitle, DrawerClose } from '@sectile/vue/drawer'
import { ref } from 'vue'
const open = ref(false)
</script>
<template>
<DrawerRoot v-model:open="open">
<DrawerTrigger>Open filters</DrawerTrigger>
<DrawerOverlay class="drawer-overlay" />
<DrawerContent class="drawer-content">
<DrawerHandle class="drawer-handle" />
<DrawerTitle>Controlled filters</DrawerTitle>
<DrawerClose>Done</DrawerClose>
</DrawerContent>
</DrawerRoot>
</template>Outside interaction
closeOnInteractOutside controls whether a pointer interaction outside the content closes it. Elements in interactOutsideExclusions stay interactive in a modal and do not count as outside. For conditional decisions, call preventDefault() from the interact-outside event.
<DrawerRoot
:interact-outside-exclusions="[ignoredElement]"
@interact-outside="(event) => {
if (event.isInside(temporarilyIgnoredElement)) event.preventDefault()
}"
/>Swipe behavior
Dragging DrawerHandle outward dismisses the drawer. Add data-sectile-drawer-swipe-ignore to descendants such as form controls that must not begin a drag. Style motion and exit states with data-swipe="move|cancel|end", data-swiping, --sectile-drawer-swipe-movement-x, --sectile-drawer-swipe-movement-y, and --sectile-drawer-swipe-progress.
API
Vue package: @sectile/vue/drawer
DrawerRootDrawerTriggerDrawerPortalDrawerOverlayDrawerContentDrawerHandleDrawerTitleDrawerDescriptionDrawerClose
Props
DrawerRootProps
autoFocusWhether focus moves into the component when it opens.
closeOnInteractOutsideWhether interaction outside the content closes it.
defaultOpenInitial uncontrolled open state.
disabledWhether interaction is unavailable.
initialFocusElement or resolver that receives focus when the component opens.
interactOutsideExclusionsElements that stay interactive and do not count as outside interaction.
labelAccessible name announced for the control.
modalWhether open content blocks interaction with the surrounding page.
openWhether the associated popup or disclosure is open.
restoreFocusWhether focus returns to the trigger when open content closes.
sideViewport edge from which the drawer opens.
swipeThresholdPointer travel in pixels required to dismiss by swiping.
swipeToDismissWhether an outward pointer swipe may dismiss the drawer.
swipeVelocityThresholdOutward drag velocity in pixels per millisecond that dismisses the drawer.
trapFocusWhether keyboard focus stays inside open content.
unmountOnExitWhether presence-managed content is removed from the DOM after its exit motion completes.
DrawerPartProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
DrawerPortalProps
deferWhether Teleport target resolution waits until the end of the current mount or update tick.
disabledWhether interaction is unavailable.
toTeleport target for portalled content.
Slots
DrawerRootSlotProps
disabledWhether interaction is unavailable.
openWhether the associated popup or disclosure is open.
Other types
DrawerOpenChangeHandler
type DrawerOpenChangeHandler = PopupFactoryOptions['onOpenChange']DrawerInteractOutsideHandler
type DrawerInteractOutsideHandler = NonNullable<PopupFactoryOptions['onInteractOutside']>DrawerSide
type DrawerSide = 'top' | 'right' | 'bottom' | 'left'Parts
Shared scope: [data-scope="drawer"]. Combine it with a part selector to keep styles local to this component.
| Part | Selector | Role | Extra attributes |
|---|---|---|---|
trigger | [data-part="trigger"] | Opens, closes, or activates the associated content. | — |
overlay | [data-part="overlay"] | Covers surrounding content while a modal surface is open. | — |
content | [data-part="content"] | Contains the component content shown for the active state. | — |
handle | [data-part="handle"] | Provides the directional swipe dismissal surface. | aria-hidden="true" |
title | [data-part="title"] | Labels the associated content. | — |
description | [data-part="description"] | Describes the associated content or decision. | — |
close | [data-part="close"] | Closes or dismisses the current surface. | — |
Keyboard interaction
| Key | Behavior |
|---|---|
| Enter / Space | Activate the trigger or focused action. |
| Tab / Shift+Tab | Move through controls while modal focus remains inside. |
| Escape | Close the drawer and restore focus when configured. |
| Pointer swipe | Drag the handle outward past the distance or velocity threshold to dismiss. |
Accessibility
The drawer follows modal dialog semantics, exposes its edge and swipe direction, and keeps its gesture handle hidden from assistive technology.
See the corresponding WAI-ARIA pattern for the host accessibility contract.
