JGuang / HeroUI

Drawer

Slide-out panel for supplementary content and actions

Import

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

Usage

HeroUI preview

Anatomy

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

export default () => (
  <Drawer>
    <Button>Open Drawer</Button>
    <Drawer.Backdrop>
      <Drawer.Content>
        <Drawer.Dialog>
          <Drawer.Handle /> {/* Optional: Drag handle */}
          <Drawer.CloseTrigger /> {/* Optional: Close button */}
          <Drawer.Header>
            <Drawer.Heading />
          </Drawer.Header>
          <Drawer.Body />
          <Drawer.Footer />
        </Drawer.Dialog>
      </Drawer.Content>
    </Drawer.Backdrop>
  </Drawer>
);

Placement

HeroUI preview

Backdrop Variants

HeroUI preview

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.

HeroUI preview

Scrollable Content

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

HeroUI preview

Controlled State

HeroUI preview

With Form

HeroUI preview
HeroUI preview

Styling

Passing Tailwind CSS classes

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.

@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

Drawer.Footer

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

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

Local source: vendor/en/react/components/(overlays)/drawer.mdx

Generated from the pinned HeroUI v3 commit with internal links and previews adapted for JGuang.

On this page