Back to Heroui

Drawer

apps/docs/content/docs/en/react/components/(overlays)/drawer.mdx

3.2.09.9 KB
Original Source

Import

tsx
import { Drawer, Button } from "@heroui/react";

Usage

<ComponentPreview name="drawer-basic" />

Anatomy

tsx
import { Drawer, Button } from "@heroui/react";

export default () => (
  <Drawer>
    <Button>Open Drawer</Button>
    <Drawer.Backdrop>
      <Drawer.Content>
        <Drawer.Dialog>
          <Drawer.Handle />
          <Drawer.CloseTrigger />
          <Drawer.Header>
            <Drawer.Heading />
          </Drawer.Header>
          <Drawer.Body />
          <Drawer.Footer />
        </Drawer.Dialog>
      </Drawer.Content>
    </Drawer.Backdrop>
  </Drawer>
);

Placement

<ComponentPreview name="drawer-placements" />

Backdrop Variants

<ComponentPreview name="drawer-backdrop-variants" />

Non-Dismissable

Set isDismissable={false} on Drawer.Backdrop to prevent closing by clicking outside or dragging. The user must interact with the drawer's action buttons.

<ComponentPreview name="drawer-non-dismissable" />

Scrollable Content

The Drawer.Body automatically handles overflow with native scrolling. Drag-to-dismiss is excluded from the body area to avoid scroll conflicts.

<ComponentPreview name="drawer-scrollable-content" />

Controlled State

<ComponentPreview name="drawer-controlled" />

With Form

<ComponentPreview name="drawer-with-form" /> <ComponentPreview name="drawer-navigation" /> <RelatedComponents component="drawer" />

Styling

Passing Tailwind CSS classes

tsx
import { Drawer, Button } from "@heroui/react";

function CustomDrawer() {
  return (
    <Drawer>
      <Button>Open Drawer</Button>
      <Drawer.Backdrop className="bg-black/80">
        <Drawer.Content>
          <Drawer.Dialog className="bg-linear-to-br from-purple-500 to-pink-500 text-white">
            <Drawer.CloseTrigger />
            <Drawer.Header>
              <Drawer.Heading>Custom Styled Drawer</Drawer.Heading>
            </Drawer.Header>
            <Drawer.Body>
              <p>This drawer has custom styling applied via Tailwind classes.</p>
            </Drawer.Body>
            <Drawer.Footer>
              <Button slot="close">Close</Button>
            </Drawer.Footer>
          </Drawer.Dialog>
        </Drawer.Content>
      </Drawer.Backdrop>
    </Drawer>
  );
}

Customizing the component classes

To customize the Drawer component classes, you can use the @layer components directive.

Learn more.

css
@layer components {
  .drawer__backdrop {
    @apply bg-gradient-to-br from-black/50 to-black/70;
  }

  .drawer__dialog {
    @apply rounded-2xl border border-white/10 shadow-2xl;
  }

  .drawer__header {
    @apply text-center;
  }

  .drawer__close-trigger {
    @apply rounded-full bg-white/10 hover:bg-white/20;
  }
}

HeroUI follows the BEM methodology to ensure component variants and states are reusable and easy to customize.

CSS Classes

The Drawer component uses these CSS classes (View source styles):

Base Classes

  • .drawer__trigger - Trigger element that opens the drawer
  • .drawer__backdrop - Overlay backdrop behind the drawer
  • .drawer__content - Positioning wrapper for the drawer panel
  • .drawer__dialog - The drawer panel itself
  • .drawer__header - Header section for titles
  • .drawer__heading - Main title text
  • .drawer__body - Main scrollable content area
  • .drawer__footer - Footer section for actions
  • .drawer__handle - Visual drag handle indicator
  • .drawer__close-trigger - Close button element

Backdrop Variants

  • .drawer__backdrop--opaque - Opaque colored backdrop (default)
  • .drawer__backdrop--blur - Blurred backdrop with glass effect
  • .drawer__backdrop--transparent - Transparent backdrop (no overlay)

Placement Variants

  • .drawer__content--bottom - Slides up from the bottom edge (default)
  • .drawer__content--top - Slides down from the top edge
  • .drawer__content--left - Slides in from the left edge
  • .drawer__content--right - Slides in from the right edge

Dialog Variants

  • .drawer__dialog--top - Slides down from the top edge
  • .drawer__dialog--bottom - Slides up from the bottom edge
  • .drawer__dialog--left - Slides in from the left edge
  • .drawer__dialog--right - Slides in from the right edge

Interactive States

The component supports these interactive states:

  • Focus: :focus-visible or [data-focus-visible="true"] - Applied to trigger and close button
  • Hover: :hover or [data-hovered="true"] - Applied to close button on hover
  • Active: :active or [data-pressed="true"] - Applied to trigger and close button when pressed
  • Entering: [data-entering] - Applied during drawer opening animation
  • Exiting: [data-exiting] - Applied during drawer closing animation
  • Placement: [data-placement="*"] - Applied based on drawer position (top, bottom, left, right)

API Reference

Drawer

PropTypeDefaultDescription
childrenReactNode-Trigger and backdrop elements
stateUseOverlayStateReturn-Controlled overlay state

Drawer.Trigger

PropTypeDefaultDescription
childrenReactNode-Custom trigger content
classNamestring-CSS classes

Drawer.Backdrop

PropTypeDefaultDescription
variant"opaque" | "blur" | "transparent""opaque"Backdrop overlay style
isDismissablebooleantrueClose on backdrop click
isKeyboardDismissDisabledbooleanfalseDisable ESC key to close
isOpenboolean-Controlled open state
onOpenChange(isOpen: boolean) => void-Open state change handler
classNamestring | (values) => string-Backdrop CSS classes

Drawer.Content

PropTypeDefaultDescription
placement"top" | "bottom" | "left" | "right""bottom"Edge the drawer slides from
classNamestring | (values) => string-Content CSS classes

Drawer.Dialog

PropTypeDefaultDescription
childrenReactNode-Dialog content
classNamestring-CSS classes
rolestring"dialog"ARIA role
aria-labelstring-Accessibility label
aria-labelledbystring-ID of label element

Drawer.Header

PropTypeDefaultDescription
childrenReactNode-Header content
classNamestring-CSS classes

Drawer.Heading

PropTypeDefaultDescription
childrenReactNode-Title text
classNamestring-CSS classes

Drawer.Body

PropTypeDefaultDescription
childrenReactNode-Body content
classNamestring-CSS classes
PropTypeDefaultDescription
childrenReactNode-Footer content
classNamestring-CSS classes

Drawer.Handle

PropTypeDefaultDescription
classNamestring-CSS classes

Drawer.CloseTrigger

PropTypeDefaultDescription
childrenReactNode-Custom close button
classNamestring | (values) => string-CSS classes

useOverlayState Hook

tsx
import { useOverlayState } from "@heroui/react";

const state = useOverlayState({
  defaultOpen: false,
  onOpenChange: (isOpen) => console.log(isOpen),
});

state.isOpen; // Current state
state.open(); // Open drawer
state.close(); // Close drawer
state.toggle(); // Toggle state
state.setOpen(); // Set state directly

Accessibility

Implements WAI-ARIA Dialog pattern:

  • Focus trap: Focus locked within drawer when open
  • Keyboard: ESC closes (when dismissable), Tab cycles elements
  • Screen readers: Proper ARIA attributes via React Aria
  • Scroll lock: Body scroll disabled when open
  • Drag to dismiss: Supports pointer-based drag gestures on handle, header, and footer areas