Drawer
Drawer composes Base UI’s drawer primitives for panels that slide over the current screen. Pass a consumer-owned React element to trigger to open it from the control that fits your flow.
import { Button, Drawer, Skeleton } from "density-base-ui";
export default function DrawerExample() {
return (
<Drawer
trigger={
<Button type="button" emphasis="outline">
Show filters
</Button>
}
title="Filters"
subtitle="Refine visible rows by status, owner, and update time."
dismissable
actions={[{ label: "Apply filters", emphasis: "primary" }]}
>
<Skeleton />
<Skeleton />
<Skeleton />
<Skeleton />
<Skeleton />
<Skeleton />
</Drawer>
);
}Drawers are right-sided on desktop. Below 768px, every drawer becomes a bottom drawer and can be dismissed by dragging its handle; content remains available for normal scrolling and interaction.
Dismiss control
Set dismissable to add a Close control alongside the drawer’s existing actions.
import { Button, Drawer, Skeleton } from "density-base-ui";
export default function DrawerDismissableExample() {
return (
<Drawer dismissable title="Filters" trigger={<Button>Show filters</Button>}>
<Skeleton style={{ height: "6rem" }} />
</Drawer>
);
}Custom trigger
import { Button, Drawer, Skeleton } from "density-base-ui";
export default function DrawerTriggerExample() {
return (
<Drawer
trigger={
<Button type="button" emphasis="outline">
Show filters
</Button>
}
title="Filters"
>
<Skeleton style={{ height: "5rem", width: "100%" }} />
</Drawer>
);
}Size
import { Button, Drawer, Skeleton, View } from "density-base-ui";
export default function DrawerSizeExample() {
return (
<View align="center" gap="md" orientation="horizontal" padding={false} wrap>
<Drawer
trigger={<Button type="button">2xs</Button>}
size="2xs"
title="Title"
>
<Skeleton />
</Drawer>
<Drawer
trigger={<Button type="button">xs</Button>}
size="xs"
title="Title"
>
<Skeleton />
</Drawer>
<Drawer
trigger={<Button type="button">sm</Button>}
size="sm"
title="Title"
>
<Skeleton />
</Drawer>
<Drawer
trigger={<Button type="button">md</Button>}
size="md"
title="Title"
>
<Skeleton />
</Drawer>
<Drawer
trigger={<Button type="button">lg</Button>}
size="lg"
title="Title"
>
<Skeleton />
</Drawer>
<Drawer
trigger={<Button type="button">xl</Button>}
size="xl"
title="Title"
>
<Skeleton />
</Drawer>
<Drawer
trigger={<Button type="button">2xl</Button>}
size="2xl"
title="Title"
>
<Skeleton />
</Drawer>
<Drawer
trigger={<Button type="button">3xl</Button>}
size="3xl"
title="Title"
>
<Skeleton />
</Drawer>
</View>
);
}Content
import { Button, Drawer, Skeleton } from "density-base-ui";
export default function DrawerContentExample() {
return (
<Drawer
trigger={<Button type="button">Open drawer</Button>}
title="Title"
subtitle="Subtitle"
closeLabel="Dismiss"
dismissable
>
<Skeleton style={{ height: "5rem", width: "100%" }} />
</Drawer>
);
}Actions
Use actions for footer choices in their supplied order. Action color remains independent of emphasis, so the action can keep the hierarchy appropriate to its drawer.
import { Button, Drawer, Skeleton } from "density-base-ui";
export default function DrawerActionsExample() {
return (
<Drawer
trigger={<Button type="button">Open drawer</Button>}
actions={[
{ label: "Later" },
{ label: "Delete project", color: "destructive", emphasis: "primary" },
]}
>
<Skeleton style={{ height: "5rem", width: "100%" }} />
</Drawer>
);
}Color
Set action color to destructive, warning, or success for semantic action color.
import { Button, Drawer, Skeleton } from "density-base-ui";
export default function DrawerColorExample() {
return (
<Drawer
trigger={<Button type="button">Open drawer</Button>}
actions={[
{ label: "Save", color: "success" },
{ label: "Escalate", color: "warning" },
{ label: "Delete", color: "destructive" },
]}
>
<Skeleton style={{ height: "5rem", width: "100%" }} />
</Drawer>
);
}Padding
import { Button, Drawer, Skeleton, View } from "density-base-ui";
export default function DrawerPaddingExample() {
return (
<View align="center" gap="md" orientation="horizontal" padding={false} wrap>
<Drawer
trigger={<Button type="button">No padding</Button>}
padding={false}
>
<Skeleton />
</Drawer>
<Drawer trigger={<Button type="button">Default padding</Button>}>
<Skeleton />
</Drawer>
</View>
);
}| Prop | Values | Required | Default | Behavior | Description |
|---|---|---|---|---|---|
actions | FormAction[] | Not required | — | — | — |
children | (React.ReactNode | import("@base-ui/react/utils/popups/popupStoreUtils").PayloadChildRenderFunction<unknown>) & React.ReactNode | Not required | — | — | The content of the drawer. |
childrenEnd | React.ReactNode | Not required | — | — | — |
childrenStart | React.ReactNode | Not required | — | — | — |
closeLabel | React.ReactNode | Not required | "Close" | — | — |
dismissable | false, true | Not required | false | — | — |
emphasis | primary, secondary, outline, ghost-primary, ghost-secondary, ghost-tertiary | Not required | — | — | — |
padding | false, true | Not required | true | Attribute: data-dn-padding | — |
size | 2xs, xs, sm, md, lg, xl, 2xl, 3xl | Not required | — | Attribute: data-dn-size | — |
subtitle | React.ReactNode | Not required | — | — | — |
title | React.ReactNode | Not required | — | — | — |
trigger | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Not required | — | — | — |
This component also accepts props from native APIs. They are passed through and intentionally kept out of this focused Density API table.