Drawer
Swipeable slide-in panel with snap points for mobile-friendly interactions
Preview
Installation
Usage
Examples
Directions
Open drawer from different screen edges.
Snap Points
Configure multiple snap points for the drawer to rest at different heights.
Pixel-Based Snap Points
Use pixel values for fixed snap heights that don't depend on content size.
Sequential Snap Points
Enable sequentialSnap to prevent skipping snap points during fast swipes.
Floating Variant
Use the floating variant for a more elevated, modal-like appearance with rounded corners and shadow.
Music Player
A music player demonstrating progressive disclosure with snap points: mini player, expanded controls, and full queue view.
Scrollable Content
Use DrawerBody for scrollable content that works seamlessly with swipe gestures.
With Form
Include form elements within the drawer.
Inset Footer
Use the footerVariant="inset" prop on DrawerContent for a visually separated footer with a muted background and top border.
Sticky Footer
Add className="sticky bottom-0" to DrawerFooter to keep it fixed at the bottom of the viewport as you drag the drawer down.
Non-Modal
Control modal behavior with the modal prop. modal={false} allows full page interaction with no focus trapping. modal="trap-focus" keeps focus within the drawer while still allowing page interaction.
API Reference
The Drawer component is built on top of Base UI's Dialog. All Base UI props are supported. The documentation below only covers custom props specific to our implementation.
For the complete Base UI API, see the Base UI Dialog documentation.
Props
Drawer
Root component that manages drawer state and provides context to child components. Wraps Base UI's Dialog.Root.
DrawerContent
Main drawer container with swipe gesture handling and positioning. Composes Dialog.Portal, Dialog.Backdrop, Dialog.Viewport, and Dialog.Popup. Props are forwarded to Dialog.Popup.
DrawerBody
Scrollable content area with adaptive padding based on surrounding elements. Wraps ScrollArea.
DrawerHandle
Visual drag indicator that doubles as a close button. Automatically adjusts orientation based on drawer direction.
Components
| Component | Description |
|---|---|
Drawer | Root component that manages state and provides context |
DrawerTrigger | Button that opens the drawer |
DrawerPortal | Renders drawer content into a portal |
DrawerContent | Main content container with swipe gesture handling |
DrawerHandle | Visual drag indicator (automatically adjusts for direction) |
DrawerHeader | Container for title and description with adaptive padding |
DrawerTitle | Accessible title element |
DrawerDescription | Accessible description element |
DrawerBody | Scrollable content area with adaptive padding |
DrawerFooter | Container for action buttons, supports inset variant via content |
DrawerClose | Button that closes the drawer |
useDrawer | Hook to access drawer context (direction, snap state, etc.) |
Nested Scrollable Content
Use DrawerBody for scrollable content inside the drawer. The component handles overflow automatically and adapts its padding based on surrounding elements (header, footer).
Animating Content Based on Snap Position
The drawer exposes a --drawer-snap-progress CSS custom property that animates from 0 (first snap) to 1 (last snap) as the drawer moves between snap points. This works in all browsers:
- Chrome 115+: GPU-accelerated CSS scroll-driven animation (no React re-renders)
- Other browsers: JavaScript fallback sets the variable automatically
Using the CSS Variable
Use --drawer-snap-progress directly in your styles for crossfade effects:
Or with Tailwind's arbitrary value syntax:
Conditional Logic with Render Props
CSS variables work great for visual properties like opacity, but some properties like pointer-events need conditional logic. Use the render prop pattern for these:
Render Prop Values
| Value | Description |
|---|---|
snapProgress | Progress between snap points (0 = first snap, 1 = last snap) |
dragProgress | Progress toward closed (0 = open, 1 = closed) |
isDragging | Whether currently being dragged/scrolled |
activeSnapPoint | Current active snap point value |