Appica UIUI 1.0.0

Drawer

A panel that slides in from a screen edge, with swipe-to-dismiss and snap points.

Usage

Drawer is a compound component built on Base UI's Drawer. It's a Dialog that slides in from an edge and can be swiped to dismiss — at home as a mobile bottom sheet or a desktop side panel. Pick the edge with side; the swipe direction follows it automatically. By default it's modal and dismissible, with a drag handle and a corner close button:

  • DrawerTrigger — the button that opens the drawer. Use render to project it onto your own Button (or any element).
  • DrawerContent — the portalled panel. It draws the card, backdrop, handle, focus trap, and corner close button, and accepts the shared modal props below.
  • DrawerHeader — groups the title and description with consistent spacing.
  • DrawerTitle — an <h2> that labels the panel (aria-labelledby).
  • DrawerDescription — a <p> that describes it (aria-describedby).
  • DrawerBody — the main content region; it owns the scroll and coordinates with the swipe gesture so scrolling doesn't dismiss the drawer.
  • DrawerFooter — the actions, stacked at the bottom of the panel.
  • DrawerClose — a button that dismisses the drawer; project it onto your own Button with render.

Reach for a Drawer when the surface should feel anchored to an edge or be swipeable on touch — navigation, filters, a detail panel, a mobile sheet. For a centered modal, use a Dialog; for a high-stakes confirmation, use an Alert Dialog.

Examples

Sides

Set side to top, right, bottom, or left to choose the edge the drawer slides in from; the swipe-to-dismiss direction follows. Left and right read as side panels; top and bottom as sheets — cap the sheet's width (here mx-auto max-w-2xl) so it doesn't stretch edge-to-edge on a wide screen.

Snap points

Pass snapPoints to let a top or bottom drawer rest at intermediate heights. Each value is a fraction of the viewport (01), a pixel number (> 1), or a CSS length string ('24rem'). The drawer opens at the first point and the user can drag — or flick — between them; it dismisses past the smallest. Great for a bottom sheet that peeks, then expands to full height.

Scrollable content

For content taller than the panel, let a ScrollArea own the overflow between a pinned header and footer. A left/right drawer is the natural fit: its swipe-to-dismiss is horizontal, so it never fights the vertical scroll.

Nested drawers

A drawer can open another drawer. Base UI keeps the parent mounted and tucks it back as the child slides in, so the stack reads as depth. The child's backdrop is suppressed automatically — just nest the markup, each drawer manages its own state.

RTL

Every Appica UI component supports right-to-left layouts out of the box. Set the dir attribute on a container (commonly your <html> element) so CSS logical properties resolve correctly, and wrap your tree in DirectionProvider so direction-aware behavior follows the same direction.

The header, body, and footer flip to read right-to-left, and the handle and corner close button move to mirror. The panel portals to <body>, so it follows the document direction — when you scope RTL to a subtree of an LTR page, set dir="rtl" on DrawerContent so the panel mirrors too. For setup details and caveats, see the RTL guide.

API reference

Drawer wraps Base UI's Drawer. Each part forwards every remaining prop to the matching Base UI primitive, so anything it accepts works here — the tables below list the Appica additions and the most common props. See the Base UI docs for the complete API.

Drawer

The root. Holds the open state and the chosen edge; renders no DOM of its own. The swipe direction is derived from side, so you don't set swipeDirection yourself.

DrawerTrigger

The button that opens the drawer. Forwards Base UI's Drawer.Trigger; use render to project it onto your own element.

DrawerContent

The portalled panel. Draws the card, backdrop, drag handle, focus trap, and corner close button, and maps the underlying Base UI Portal / Backdrop / Viewport so you don't have to reach into them. Shared with Dialog and Alert Dialog through the modal props.

DrawerHeader

A layout wrapper that groups the title and description with consistent padding and spacing.

DrawerTitle

An <h2> that labels the panel. Rendering one sets the panel's aria-labelledby.

DrawerDescription

A <p> that describes the panel. Rendering one sets the panel's aria-describedby.

DrawerBody

The main content region. Owns the scroll for overflowing content and coordinates with the swipe gesture so scrolling away from the edge doesn't dismiss the drawer.

DrawerFooter

A layout wrapper for the actions, stacked at the bottom of the panel.

DrawerClose

A button that closes the drawer. Forwards Base UI's Drawer.Close; project it onto your own element with render.

Indenting the page

Three optional parts — all from @appica/ui-react/drawer — produce the effect where the page scales back as a drawer opens. Wrap your app once at the root; most drawers never touch them.

Accessibility

  • The panel has role="dialog" with aria-modal, and aria-labelledby / aria-describedby wired automatically from DrawerTitle and DrawerDescription — always render a title.
  • Opening traps focus inside the panel; Escape, an outside click, or a swipe toward the edge close it (set disablePointerDismissal to keep it open on a backdrop click), and focus returns to the trigger.
  • With modal (the default), scroll and interaction with the rest of the page are blocked while the drawer is open. Set modal={false} to leave the page interactive.
  • The corner close button carries an accessible label (closeLabel, default "Close"); set it when your drawer needs more specific wording.
  • Swipe-to-dismiss, snap transitions, and enter/exit animations are skipped when the user prefers reduced motion.

© 2026 Appica UI. A free component library, crafted by the Appica team.