Skip to main content

Drawer

A drawer is a panel that slides in from the edge of the screen. It’s often used for navigation or displaying contextual information without navigating away from the current page.

Import

import { Drawer } from '@base-ui/react/drawer';

Basic Usage

<Drawer.Root>
  <Drawer.Trigger>Open Menu</Drawer.Trigger>
  <Drawer.Portal>
    <Drawer.Backdrop />
    <Drawer.Popup>
      <Drawer.Title>Navigation</Drawer.Title>
      <Drawer.Description>Browse the site</Drawer.Description>
      <nav>
        <a href="/home">Home</a>
        <a href="/about">About</a>
        <a href="/contact">Contact</a>
      </nav>
      <Drawer.Close>Close</Drawer.Close>
    </Drawer.Popup>
  </Drawer.Portal>
</Drawer.Root>

Sub-components

Root

Groups all parts of the drawer. Doesn’t render its own HTML element. Key Props:
  • open (boolean): Whether the drawer is currently open
  • defaultOpen (boolean): Whether the drawer is initially open (default: false)
  • modal (boolean | ‘trap-focus’): Determines if the drawer enters a modal state (default: true)
  • onOpenChange ((open: boolean, eventDetails) => void): Event handler called when the drawer is opened or closed
  • onOpenChangeComplete ((open: boolean) => void): Event handler called after animations complete
  • disablePointerDismissal (boolean): Determines whether the drawer should close on outside clicks (default: false)
  • swipeDirection (‘up’ | ‘down’ | ‘left’ | ‘right’): The swipe direction used to dismiss the drawer (default: 'down')
  • snapPoints (Array): Snap points used to position the drawer (numbers 0-1 for fractions, >1 for pixels, or strings like '148px')
  • snapPoint (number | string | null): The currently active snap point (controlled)
  • defaultSnapPoint (number | string | null): The initial snap point value when uncontrolled
  • snapToSequentialPoints (boolean): Disables velocity-based snap skipping (default: false)
  • onSnapPointChange ((snapPoint, eventDetails) => void): Callback fired when the snap point changes
  • handle (DialogHandle): A handle to associate the drawer with an external trigger
  • actionsRef (React.RefObject): A ref to imperative actions (unmount, close)

Trigger

The button that opens the drawer.

Portal

Portals the drawer content to a different part of the DOM.

Backdrop

The backdrop that covers the screen when the drawer is open. The container for the drawer content.

Content

The main content area of the drawer.

Title

An accessible title for the drawer.

Description

An accessible description for the drawer.

Close

A button that closes the drawer.

Viewport

Defines the viewport element to which the drawer is confined.

Provider

Provides drawer context to nested drawers.

Indent

Creates an indent effect for nested drawers.

IndentBackground

The background for the indent effect.

Styling Example

.DrawerBackdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  transition: opacity 200ms;
}

.DrawerPopup {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: white;
  border-radius: 16px 16px 0 0;
  padding: 24px;
  max-height: 90vh;
  transform: translateY(100%);
  transition: transform 300ms cubic-bezier(0.32, 0.72, 0, 1);
}

.DrawerPopup[data-open] {
  transform: translateY(0);
}

.DrawerTitle {
  font-size: 1.25rem;
  font-weight: 600;
  margin: 0 0 8px;
}

Key Features

  • Swipe to dismiss in configurable directions
  • Snap points for partial drawer states
  • Nested drawer support with indent effects
  • Android back gesture support (Chromium-only)
  • Smooth animations with spring physics
  • Keyboard navigation support

Accessibility

  • Has role="dialog" to identify it as a dialog
  • Title and description are automatically linked via aria-labelledby and aria-describedby
  • Focus is trapped within the drawer when modal
  • The backdrop and outside elements are inert when the drawer is modal
  • Pressing Escape closes the drawer
  • Android back button/gesture support via CloseWatcher API