Drawer
Overviewimport { Drawer, DrawerFooter, DrawerHeader, DrawerSide } from '@nili/ui';This is the library’s own overview page, rendered live. Switch the language or the theme in the header and it follows.
Basic
A panel that slides in from an edge. Controlled by open and onOpenChange, like Modal — it portals, traps focus, and returns focus to the trigger.
import { Drawer, Button, TextInput } from "@nili/ui"
export function Example() {
const [open, setOpen] = useState(false)
return (
<>
<Button onClick={() => setOpen(true)}>Open drawer</Button>
<Drawer
open={open}
onOpenChange={setOpen}
title="Filters"
description="Narrow the list down."
closeLabel="Close"
footer={
<>
<Button appearance="stroke" onClick={() => setOpen(false)}>Reset</Button>
<Button onClick={() => setOpen(false)}>Apply</Button>
</>
}
>
<TextInput
label={t('filters.search')}
placeholder={t('filters.searchPlaceholder')}
/>
</Drawer>
</>
)
}Sides
side is logical: end is right in English and left in Persian, so the drawer always opens from the edge the reader expects. top and bottom are physical, because there is no reading direction on that axis.
import { Drawer } from "@nili/ui"
export function Example() {
return (
<>
<Drawer side="end" … />
<Drawer side="start" … />
<Drawer side="top" … />
<Drawer side="bottom" … />
</>
)
}Sizes and header density
Four panel sizes, and a separate headerSize for Figma's Small / Large header.
import { Drawer } from "@nili/ui"
export function Example() {
return (
<>
<Drawer size="sm" headerSize="sm" … />
<Drawer size="lg" headerSize="lg" … />
<Drawer size="full" … />
</>
)
}Stretched footer
stretchFooter makes the actions fill the width — Figma's footer Stretch. Right on a narrow drawer, where two hugging buttons leave an awkward gap.
import { Drawer, Button } from "@nili/ui"
export function Example() {
return (
<Drawer
open={open}
onOpenChange={setOpen}
title="Settings"
stretchFooter
footer={
<>
<Button appearance="stroke" onClick={close}>Cancel</Button>
<Button onClick={close}>Save</Button>
</>
}
/>
)
}Controlling dismissal
closeOnOutsideClick and closeOnEscape are on by default. showClose keeps the ✕ — leave it when you turn the other two off, or the drawer has no exit.
import { Drawer } from "@nili/ui"
export function Example() {
return (
<Drawer
open={open}
onOpenChange={setOpen}
closeOnOutsideClick={false}
closeOnEscape={false}
showClose
closeLabel="Close"
title="Editing"
…
/>
)
}Drawer
extends Omit< ComponentPropsWithoutRef<'div'>, 'title' | 'children' >
Other props
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | — | |
| aria-label | string | — | |
| open* | boolean | — | |
| onOpenChange* | (open: boolean) => void | — | |
| side | start | end | top | bottom | end | Logical: `end` is right in English, left in Persian. |
| size | lg | md | sm | full | md | |
| title | ReactNode | — | |
| description | ReactNode | — | |
| icon | ReactNode | — | Figma header "Left Icon" — leading slot before the title. |
| headerSize | sm | lg | sm | Header density: Figma's Small / Large. |
| footer | ReactNode | — | |
| stretchFooter | boolean | false | Figma footer "Stretch": actions fill the width. |
| showClose | boolean | true | |
| closeLabel | string | Close | |
| closeOnOutsideClick | boolean | true | |
| closeOnEscape | boolean | true | |
| container | HTMLElement | null | — | Where to portal the drawer. Defaults to `document.body`. |
DrawerBody
internalVariant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| size | sm | lg | sm |
DrawerFooter
Variant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| stretch | 'true' | 'false' | false |
DrawerHeader
Variant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| size | sm | lg | sm |
Other props
| Prop | Type | Default | Notes |
|---|---|---|---|
| title | ReactNode | — | |
| description | ReactNode | — | |
| icon | ReactNode | — | A 20px icon, or a 48px key icon. |
| titleId | string | — | |
| descriptionId | string | — | |
| onClose | () => void | — | Shows the × when set. |
| closeLabel | string | Close | |
| className | string | — |
DrawerOverlay
internalDrawerPanel
internalVariant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| side | start | end | top | bottom | end | |
| size | sm | md | lg | full | md |