import { Button } from "@hel/ui/button"
import { Checkbox, CheckboxLabel } from "@hel/ui/checkbox"
import {When to use it#
Use a drawer for work that is bigger than a popover but should keep the person in the context of the page: editing a record from a list, a filter panel, a navigation menu on a phone. It slides in from an edge, and the page behind it stays in place.
On a small screen a drawer from the bottom feels natural, because people can swipe it away with a thumb. For a short question or a small form in the middle of the screen, use a Dialog.
Import#
import {
Drawer,
DrawerTrigger,
DrawerContent,
DrawerHeader,
DrawerTitle,
DrawerDescription,
DrawerBody,
DrawerFooter,
DrawerClose,
} from "@hel/ui/drawer"Anatomy#
Drawer holds the open state, and DrawerTrigger opens it. DrawerContent is the panel, together with the dimmed backdrop. It is split into three parts, so that long content scrolls in the right place:
DrawerHeaderis fixed at the top. It groups theDrawerTitleand theDrawerDescription, and has a close button at the end of the row. SetshowClose={false}to leave the button out.DrawerBodyis the only part that scrolls.DrawerFooteris pinned to the bottom, for the buttons.
DrawerClose closes the drawer when its element is pressed. Pass the button with render, so the two are one element.
<Drawer>
<DrawerTrigger render={<Button variant="outline">Edit customer</Button>} />
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Edit customer</DrawerTitle>
</DrawerHeader>
<DrawerBody>...</DrawerBody>
<DrawerFooter>
<DrawerClose render={<Button variant="outline">Cancel</Button>} />
</DrawerFooter>
</DrawerContent>
</Drawer>Escape, a click on the backdrop, and a swipe toward the edge it came from all close the drawer.
Examples#
Sides#
side on Drawer is the edge the panel comes from: right, the default, left or bottom. The direction of the swipe that closes it follows automatically, so the gesture and the edge always match. A bottom drawer shows a small grab handle at the top, which tells people it can be swiped. Use showHandle on the content to turn it on or off for any side.
import { Button } from "@hel/ui/button"
import {
Drawer,Looks#
The panel floats a little away from the edge of the screen, with rounded corners. margin on DrawerContent sets that gap, using the spacing scale, and it defaults to sm. disableAnimation removes the slide and fade.
Nested drawers#
A drawer inside the body of another drawer is treated as nested. The first one steps back slightly while the second is open, so the stack is easy to read.
Props#
Drawer#
| Prop | Type | Default |
|---|---|---|
side | "right" | "left" | "bottom" | "right" |
open / defaultOpen | boolean | false |
onOpenChange | (open: boolean) => void | none |
modal | boolean | true |
It also takes every prop of the Base UI drawer.
DrawerContent#
| Prop | Type | Default |
|---|---|---|
margin | a spacing step | "sm" |
showHandle | boolean | true for bottom, otherwise false |
container | an element | The page |
disableAnimation | boolean | false |
DrawerHeader#
| Prop | Type | Default |
|---|---|---|
showClose | boolean | true |