Drawer

A swipeable panel that appears from the edge of the page.
vue
<script setup lang="ts">
import { ref } from 'vue'
import { Button, DrawerRoot, DrawerTrigger, DrawerPopup, DrawerTitle, DrawerDescription, DrawerCloseButton } from '@typlog/ui'

const open = ref(false)
</script>
<template>
  <DrawerRoot v-model:open="open">
    <DrawerTrigger as-child>
      <Button>Open drawer</Button>
    </DrawerTrigger>
    <DrawerPopup>
      <DrawerTitle>Share this page</DrawerTitle>
      <DrawerDescription>Choose where you want to share this page.</DrawerDescription>
      <div class="flex gap-2 mt-5">
        <Button>Copy link</Button>
        <Button variant="soft" color="gray">Share</Button>
      </div>
      <DrawerCloseButton />
    </DrawerPopup>
  </DrawerRoot>
</template>

API Reference ​

DrawerRoot ​

Contains the drawer parts and supports controlled state, swipe direction, and snap points.

PropDefaultType
defaultOpen
–
boolean
defaultSnapPoint
–
DrawerSnapPointnull
modal
–
DrawerModal

Modality of the drawer.

  • true (default): modal with focus trap, scroll lock, and outside-press dismiss
  • 'trap-focus': traps focus but allows outside pointer events (non-modal side panels)
  • false: non-modal
open
–
boolean

v-model:open

snapPoint
–
DrawerSnapPointnull

v-model:snapPoint

snapPoints
–
DrawerSnapPoint[]

Preset snap positions (fractions 0-1, pixels >1, or '148px'/'30rem' strings)

snapToSequentialPointsfalse
boolean

When true, snaps to the next sequential snap point (one step at a time). When false, snaps to the nearest snap point by distance.

swipeDirection'down'
SwipeDirection$1

Direction to swipe to dismiss.

DrawerPopup ​

The styled, portalled drawer content. Use :show-handle="false" to hide the default drag handle.

PropDefaultType
showHandletrue
boolean

Render a draggable handle.

size"2"
"1""2""3"

Control the size of the drawer.

ui
–
DrawerPopupUI

Classes for the component's stable visual parts.

DrawerTrigger, DrawerClose & DrawerSwipeArea ​

These are unstyled Reka UI primitives re-exported for composing drawer interactions. Their props are forwarded without modification; see the linked Reka UI reference.

DrawerHandle ​

The styled drag affordance rendered by DrawerPopup when showHandle is enabled.

DrawerTitle & DrawerDescription ​

Accessible labelling parts for the drawer.

DrawerCloseButton ​

A styled close button with a tooltip.

PropDefaultType
as"button"
AsTagComponent

The element or component this component should render as.

asChild
–
boolean
color"gray"

Overrides the accent color inherited from the ThemeProvider.

disabled
–
boolean

Mark the button as disabled.

highContrastfalse
boolean

Uses a higher contrast color for the component.

radius
–
"none""small""medium""large""full"

Overrides the radius inherited from the ThemeProvider.

size"2"
"1""2""3""4"

Control the size of the button.

tooltip"Close"
string
variant"ghost"
Enum

The visual variant to apply.

Examples ​

Directions ​

Set swipe-direction to up, down, left, or right.

vue
<script setup lang="ts">
import { Button, DrawerRoot, DrawerTrigger, DrawerPopup, DrawerTitle } from '@typlog/ui'

const directions = ['down', 'up', 'left', 'right'] as const
</script>
<template>
  <div class="flex flex-wrap gap-2">
    <DrawerRoot v-for="direction in directions" :key="direction" :swipe-direction="direction">
      <DrawerTrigger as-child>
        <Button variant="soft" color="gray">{{ direction }}</Button>
      </DrawerTrigger>
      <DrawerPopup>
        <DrawerTitle>{{ direction }} drawer</DrawerTitle>
        <p class="mt-3">Swipe or press Escape to close.</p>
      </DrawerPopup>
    </DrawerRoot>
  </div>
</template>

Snap points ​

Use snap-points with v-model:snap-point to provide draggable intermediate positions.

vue
<script setup lang="ts">
import { ref } from 'vue'
import { Button, DrawerClose, DrawerDescription, DrawerPopup, DrawerRoot, DrawerTitle, DrawerTrigger } from '@typlog/ui'

const snapPoint = ref<number | string | null>(0.5)
</script>

<template>
  <DrawerRoot v-model:snap-point="snapPoint" :snap-points="[0.25, 0.5, 1]">
    <DrawerTrigger as-child>
      <Button>Open with snap points</Button>
    </DrawerTrigger>
    <DrawerPopup>
      <DrawerTitle>Resizable drawer</DrawerTitle>
      <DrawerDescription>Drag the handle to move between snap points.</DrawerDescription>
      <p class="mt-4">Current snap point: {{ snapPoint }}</p>
      <Button class="mt-4" variant="soft" color="gray" :as="DrawerClose">Close</Button>
    </DrawerPopup>
  </DrawerRoot>
</template>
Last updated Sep 15, 2026