Drawer
React Drawer components are gesture-driven panels that slide in from the edge of the screen. Unlike a standard Sheet, a Drawer supports drag-to-dismiss gestures, making it feel native and highly interactive, especially on mobile devices.
This Drawer component is built with React Aria for accessibility, Framer Motion for fluid gesture animations, and Tailwind CSS for styling. It supports all four sides and includes a customizable drag handle.
Installation
Install the component using the Tailgrids CLI.
npx @tailgrids/cli add drawerAnatomy
The Drawer follows a composable pattern similar to the Sheet, but with built-in gesture support and a drag handle.
import {
Drawer,
DrawerTrigger,
DrawerContent,
DrawerHeader,
DrawerTitle,
DrawerDescription,
DrawerBody,
DrawerFooter,
DrawerClose
} from "@/registry/core/drawer";
export default function DrawerAnatomy() {
return (
<Drawer>
<DrawerTrigger />
<DrawerContent side="bottom">
<DrawerHeader>
<DrawerTitle />
<DrawerDescription />
</DrawerHeader>
<DrawerBody />
<DrawerFooter>
<DrawerClose />
</DrawerFooter>
</DrawerContent>
</Drawer>
);
}Usage
Create a drawer by composing the necessary components inside a root Drawer.
import {
Drawer,
DrawerTrigger,
DrawerContent,
DrawerHeader,
DrawerTitle,
DrawerDescription
} from "@/registry/core/drawer";
export default function DrawerExample() {
return (
<Drawer>
<DrawerTrigger>Open Drawer</DrawerTrigger>
<DrawerContent side="bottom">
<DrawerHeader>
<DrawerTitle>Options</DrawerTitle>
<DrawerDescription>
Manage your preferences here. Swipe down to close.
</DrawerDescription>
</DrawerHeader>
</DrawerContent>
</Drawer>
);
}Examples
Custom Sides
The side prop on DrawerContent allows you to control the entry point of the drawer. Options are top, right, bottom, and left. The drag handle and gesture axis automatically adapt to the chosen side.
Profile View
Use a drawer to display a quick profile overview or user details. The gesture-driven nature makes it feel like a native mobile app interaction.
Quick Settings
Drawers are excellent for quick settings or filters that users might want to tweak without leaving their current context.
Long Scrollable Content
Use DrawerBody for content that might exceed the screen height. The body will automatically scroll while keeping the header and footer fixed. The drag gesture intelligently handles the difference between scrolling the content and dragging the drawer itself.
API Reference
Drawer
The root component that manages the open/close state of the drawer.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | The trigger and content elements |
isOpen | boolean | - | Controlled open state |
defaultOpen | boolean | - | Uncontrolled default open state |
onOpenChange | (isOpen: boolean) => void | - | Called when the open state changes |
DrawerTrigger
The element that opens the drawer when pressed.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | The trigger label or element |
className | string | - | Additional CSS classes |
DrawerContent
The primary layout component for the drawer panel. It handles the drag gestures, animations, and renders the drag handle automatically.
| Prop | Type | Default | Description |
|---|---|---|---|
side | top | right | bottom | left | "bottom" | The edge of the screen the drawer slides from |
children | React.ReactNode | (opts: { close: () => void }) => React.ReactNode | - | Content of the drawer. Supports render props for close() access |
showCloseButton | boolean | true | Whether to show the default close button in the top-right |
snapThreshold | number | - | Threshold (in px) at which the drawer snaps closed. Defaults to 30% of viewport size |
className | string | - | Additional CSS classes for the drawer panel |
DrawerHeader
A wrapper for the title and description at the top of the drawer.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Header content |
className | string | - | Additional CSS classes |
DrawerTitle
The accessible heading for the drawer.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Title text |
className | string | - | Additional CSS classes |
DrawerDescription
Secondary text for the drawer header.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Description text |
className | string | - | Additional CSS classes |
DrawerBody
A scrollable container for the main content of the drawer.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Body content |
className | string | - | Additional CSS classes |
DrawerFooter
An action bar section at the bottom of the drawer.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Footer content |
showCloseButton | boolean | false | Whether to render a built-in "Close" button |
className | string | - | Additional CSS classes |
DrawerClose
A specialized button that automatically closes the nearest drawer.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | The close button label/content |
className | string | - | Additional CSS classes |
Accessibility
- Focus Management: Focus is automatically trapped inside the drawer when open and restored to the trigger element on close.
- Keyboard Navigation: Pressing
Escapeor the close trigger closes the drawer. - ARIA Labeling:
DrawerTitleusesslot="title"to provide an accessible label for the drawer component. - Screen Readers: The drawer is announced as a modal overlay, and background content is hidden from assistive technology when open.
- Gestures: The drag-to-dismiss gesture provides an alternative, intuitive way to close the drawer, especially beneficial for touch users.