API and Development
Drawer from @prepared911/ui/drawer is a panel that slides in from a viewport edge. Drawer owns open state. DrawerPanel is the surface (edge, size, title or aria-label, closeLabel). DrawerHeader, DrawerContent, DrawerFooter, and DrawerNav fill it. A shell that swaps several bodies in one panel uses DrawerHost and createDrawerHostStore from @prepared911/ui/blocks/drawer-host. There is no module-global drawer store and no portal node to mount.
A portaled drawer with header, scrollable list body, one expandable section, and a footer—similar to detail panels when reviewing historical (archived) incidents in dispatch.
| Name | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | {@link DialogTrigger } and {@link DialogContent }, in any order. |
defaultOpen | boolean | false | Initial open state when uncontrolled. |
finalFocus | PopupFocusTarget | — | Focused after every close. Omit to return focus to the element that was focused before the dialog opened. |
initialFocus | PopupFocusTarget | — | Focused right after the dialog opens. Omit for the first control, or an autofocus element; a scroller never takes it unless it is a labelled tab stop. |
modal | boolean | true | When true, opens with showModal(): scrim, page inertness, and focus trap. When false, opens with show();
the page stays interactive and an outside press closes with light-dismiss. |
onOpenChange | ((open: boolean, details: DialogOpenChangeDetails) => void) | — | Called once per open or close request: trigger press, close press, Escape (close-request), and a
method="dialog" form submit (form-submit). A cancelable request is vetoed with details.cancel(). |
open | boolean | — | Controlled open state. Pair with {@link DialogProps.onOpenChange}. |
resizable and resizeLabel on DrawerPanel. The width stays on the DrawerSize steps (Small, Medium, Large) and clamps between Small and Large while dragging. There is no free width, minWidth, or maxWidth.
An open drawer publishes its extent on the document as --ds-drawer-reserve-inline-start, --ds-drawer-reserve-inline-end, --ds-drawer-reserve-block-start, and --ds-drawer-reserve-block-end. onSizeChange on DrawerPanel reports the same extent in JavaScript. A layout that must ignore one drawer reads onSizeChange from the panels it cares about.
DrawerNav renders fixed segmented navigation between DrawerHeader and DrawerContent. Set collapseUnselectedLabels to keep the active item label open while collapsing inactive items to their icons. Collapsible DrawerNavItem entries must provide both icon and aria-label.
| Name | Type | Default | Description |
|---|---|---|---|
value | string | — | Controlled selected segment value. |
defaultValue | string | — | Initial uncontrolled segment value. |
onValueChange | (value: string) => void | — | Runs when selection changes. |
fullSpan | boolean | false | Expands segments evenly across the nav width. |
collapseUnselectedLabels | boolean | false | Collapses inactive labels to their icons. |
actions | ReactNode | — | Controls pinned to the right of the nav. |
border | boolean | true | Renders the nav bottom border. |
mergeWithHeader | boolean | true | Merges compact nav chrome with the preceding header. |
dragToScroll | boolean | true | Enables horizontal drag-to-scroll for overflowing items. |