Drawer

A drawer slides in from the edge of the screen to display content.

<Dialog>
  <Button>Open Drawer</Button>
  <Drawer>
    <DialogContent>
      <DialogHeader>
        <DialogTitle>Drawer Title</DialogTitle>
        <DialogDescription>This is a drawer description.</DialogDescription>
      </DialogHeader>
      <DialogBody>
        <p>Drawer content goes here.</p>
      </DialogBody>
      <DialogFooter>
        <Button slot="close">Close</Button>
      </DialogFooter>
    </DialogContent>
  </Drawer>
</Dialog>

Installation

npx shadcn@latest add @dotui/drawer

Usage

Use drawers to display content that slides in from the edge of the screen.

import { Button } from '@/components/ui/button'
import { Dialog, DialogContent } from '@/components/ui/dialog'
import { Drawer } from '@/components/ui/drawer'
<Dialog>
  <Button>Open Drawer</Button>
  <Drawer placement="bottom">
    <DialogContent>Drawer content</DialogContent>
  </Drawer>
</Dialog>

Anatomy

A Drawer has no built-in trigger. Wrap it in a Dialog with a Button child as the trigger, and put your content inside DialogContent.

import { Button } from '@/components/ui/button'
import { Dialog, DialogContent } from '@/components/ui/dialog'
import {
  Drawer,
  DrawerHandle,
  DrawerSwipeArea,
  DrawerProvider,
  DrawerIndent,
  DrawerIndentBackground,
} from '@/components/ui/drawer'
;<Dialog>
  <Button />
  <Drawer>
    <DialogContent>
      <DrawerHandle />
    </DialogContent>
  </Drawer>
</Dialog>

DrawerHandle is a visible drag affordance. DrawerSwipeArea is an edge region that opens the drawer by swiping. DrawerIndent and DrawerIndentBackground wrap page content that scales and translates behind an open drawer, and DrawerProvider scopes visual state explicitly — most apps don't need it.

Open state

Rendered under a Dialog, the drawer shares the dialog's open state, so the trigger Button opens it with no wiring. To drive it yourself, pass isOpen with onOpenChange (or defaultOpen for uncontrolled).

const [isOpen, setIsOpen] = React.useState(false)

<Drawer isOpen={isOpen} onOpenChange={setIsOpen}>
  <DialogContent>...</DialogContent>
</Drawer>

Dismissal

The drawer dismisses on swipe, outside interaction, and Escape. Disable each with swipeToDismiss, isDismissable, and isKeyboardDismissDisabled respectively.

<Drawer swipeToDismiss={false} isDismissable={false} isKeyboardDismissDisabled>
  <DialogContent>...</DialogContent>
</Drawer>

Examples

Basic Drawer

Settings Panel

Nested Drawers

Scrollable Content

Form Drawer

API Reference

Drawer

A React Aria compatible drawer overlay powered by Base UI's Drawer overlay primitives.

PropType
DrawerPlacement
boolean
boolean
boolean
ReactNode

DrawerHandle

A visible drag affordance.

Supports all div attributes.

PropType

DrawerSwipeArea

An edge region that can open the drawer by swiping.

PropType
boolean
SwipeDirection

DrawerProvider

Optional explicit visual-state scope. Most apps don't need this.

DrawerIndent

Wraps page content; scales/translates while a drawer is open.

PropType

DrawerIndentBackground

The dark layer behind the indented content.

PropType

Last updated on 7/7/2026