Drawer

New

An interactive overlay and bottom sheet component powered by Base UI with swipe-to-dismiss, snap points, nested stacks, customizable positions, and inset or straight variants.

$ pnpm dlx shadcn@latest add @byphongphan/drawer
Requires @byphongphan in components.json
interactive

Installation

Install the following dependencies:

$ pnpm add @base-ui/react lucide-react
Requires @byphongphan in components.json

Copy and paste the drawer component into your project.

components/ui/drawer.tsx

Update the import paths to match your project setup.

Usage

import { Button } from "@/components/ui/button"import {  Drawer,  DrawerClose,  DrawerDescription,  DrawerFooter,  DrawerHeader,  DrawerPanel,  DrawerPopup,  DrawerTitle,  DrawerTrigger,} from "@/components/ui/drawer"
export function DrawerDemo() { return ( <Drawer> <DrawerTrigger render={<Button variant="outline" />}> Open Drawer </DrawerTrigger> <DrawerPopup showBar> <div className="mx-auto w-full max-w-sm"> <DrawerHeader> <DrawerTitle>Drawer Title</DrawerTitle> <DrawerDescription> Drawer description goes here. </DrawerDescription> </DrawerHeader> <DrawerPanel> <p className="text-sm text-muted-foreground">Drawer content...</p> </DrawerPanel> <DrawerFooter variant="bare"> <Button>Submit</Button> <DrawerClose render={<Button variant="outline" />}> Cancel </DrawerClose> </DrawerFooter> </div> </DrawerPopup> </Drawer> )}

Examples

Inset Positioning

Floating detached drawer variant with margin offsets across all 4 screen edges: right, left, top, and bottom.

Straight Corners

Minimalist architectural variant with sharp rectangular corners (variant="straight") and no nested scaling.

Scrollable Content

Built-in smooth scrolling with overflow handling and automatic scroll fade indicators for long list views.

Nested Drawers

Multi-step nested drawer stack with dynamic depth scaling, peek offsets, and smooth breadcrumb progression.

Snap Points

Preset intermediate snap positions (such as 35%, 70%, and 100%) with velocity-aware drag thresholds and programmatic control.

Max Width Popup

Limits the entire DrawerPopup sheet width (e.g. mx-auto max-w-lg sm:border-x) on desktop viewports with clean side borders, while expanding to full width on mobile devices.


Props

Drawer

PropTypeDefaultDescription
position"bottom" | "top" | "left" | "right""bottom"Screen edge from which the drawer slides in.
swipeDirection"down" | "up" | "left" | "right"(auto)Swipe direction to dismiss; automatically synced to position when omitted.
snapPointsArray<number | string>undefinedPreset snap points (fractions e.g. 0.5, pixel heights e.g. 400, or CSS strings).
snapPointnumber | string | nullundefinedControlled active snap point value.
defaultSnapPointnumber | string | nullundefinedInitial snap point when uncontrolled.
onSnapPointChange(snapPoint, details) => voidundefinedCallback fired when the active snap point changes.
openbooleanundefinedControlled open state of the drawer.
defaultOpenbooleanfalseInitial open state when uncontrolled.
onOpenChange(open, details) => voidundefinedEvent handler called when the drawer opens or closes.
modalboolean | "trap-focus"trueTraps focus and locks background page scrolling when active.
disablePointerDismissalbooleanfalsePrevents the drawer from closing when pressing outside the popup.

DrawerPopup

PropTypeDefaultDescription
variant"default" | "straight" | "inset""default"Visual style for corners and edge margins (straight corners or floating inset).
position"bottom" | "top" | "left" | "right"(context)Overrides the parent drawer position context if specified.
showBarbooleanfalseWhether to display the tactile grab handle bar.
showCloseButtonbooleanfalseDisplays an absolute close button in the top-end corner.
portalPropsDrawerPortalPropsundefinedOptional props forwarded to the underlying DrawerPortal.

DrawerPanel

PropTypeDefaultDescription
scrollablebooleantrueAutomatically wraps panel content in a responsive Base UI ScrollArea.
scrollFadebooleantrueShows smooth top/bottom mask fade gradients when content overflows.
allowSelectionbooleantrueAllows text selection inside the panel without triggering swipe gestures.

DrawerFooter

PropTypeDefaultDescription
variant"default" | "bare""default""default" has a subtle top border and background; "bare" has no border.
allowSelectionbooleantrueAllows text and button interaction without swipe drag interference.

Command Palette

Quick search and commands navigation