Drawer
A swipeable panel that slides in from the edge of the screen.
import { Button } from '@/components/ui/button';
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/components/ui/drawer';
export default function DrawerDemo() {
return (
<Drawer showSwipeHandle>
<DrawerTrigger render={<Button variant="outline" />}>
Open drawer
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Move goal</DrawerTitle>
<DrawerDescription>Set your daily activity goal.</DrawerDescription>
</DrawerHeader>
<DrawerFooter>
<DrawerClose render={<Button />}>Submit</DrawerClose>
<DrawerClose render={<Button variant="outline" />}>Cancel</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
);
}
Install
npx shadcn@latest add @madeui/drawer
Usage
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/components/ui/drawer';
Composition
<Drawer>
<DrawerTrigger />
<DrawerContent>
<DrawerHeader>
<DrawerTitle />
<DrawerDescription />
</DrawerHeader>
<DrawerFooter>
<DrawerClose />
</DrawerFooter>
</DrawerContent>
</Drawer>
Directions
swipeDirection sets which edge the drawer rests on and swipes back toward.
import * as stylex from '@stylexjs/stylex';
import { Button } from '@/components/ui/button';
import {
Drawer,
DrawerContent,
DrawerDescription,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
type DrawerSwipeDirection,
} from '@/components/ui/drawer';
import { space } from '@/lib/constants.stylex';
const directions: DrawerSwipeDirection[] = ['up', 'right', 'down', 'left'];
export default function DrawerDirections() {
return (
<div {...stylex.props(styles.row)}>
{directions.map((direction) => (
<Drawer key={direction} swipeDirection={direction}>
<DrawerTrigger render={<Button variant="outline" />}>
{direction}
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Drawer from {direction}</DrawerTitle>
<DrawerDescription>
Rests on and swipes back toward the {direction} edge.
</DrawerDescription>
</DrawerHeader>
</DrawerContent>
</Drawer>
))}
</div>
);
}
const styles = stylex.create({
row: {
display: 'flex',
flexWrap: 'wrap',
gap: space.s2,
},
});
API reference
Built on Base UI Drawer. Swipe-to-dismiss and snap points come from the primitive — Base UI drives the swipe offsets through CSS variables that the styles consume. All props are forwarded to the Base UI Root (open, snapPoints, modal, swipeDirection, …); see the Base UI Drawer API reference.
Unlike Sheet (a fixed side panel on the Dialog primitive), Drawer is gesture-driven — prefer it on touch-first surfaces.
Drawer
| Prop | Type | Default | Description |
|---|---|---|---|
swipeDirection |
'down' | 'up' | 'left' | 'right' |
'down' |
Edge the drawer rests on and dismisses toward. |
showSwipeHandle |
boolean |
false |
Renders a grab handle on the swipe edge. |
Nested drawer stacking (scale/peek of the drawer behind) is not styled yet. Every part accepts a style prop (StyleXStyles, merged last).