Drawer
Edge-docked panel with scrim, focus trap, and Esc-to-close — inline-start/end aware.
Preview
Static preview De-roled visual mock — no focus trap/role wired, safe to render inline.
<div style="position:relative;height:260px;overflow:hidden;border:1px solid var(--nx-hairline);border-radius:14px"><div style="position:absolute;inset:0;background:var(--nx-scrim)"></div><div style="position:absolute;top:0;bottom:0;right:0;width:220px;background:var(--nx-white);border-left:1px solid var(--nx-hairline);display:flex;flex-direction:column"><div class="nx-panel__head"><span class="nx-panel__title">Filters</span><span class="nx-iconbtn">×</span></div><div class="nx-panel__body"><label class="nx-checkbox"><input type="checkbox" checked><span class="nx-checkbox__box"></span>Open</label></div></div></div><NxDrawer open title="Filters" footer={<NxButton>Apply</NxButton>}>
<NxCheckbox label="Open" defaultChecked />
</NxDrawer>Variants
Open in isolation
Mounts the real, fully-correct drawer (role=dialog, focus trap, scrim-click + Esc to close).
<button class="nx-btn nx-btn--primary" id="openDrawerDemo">Open drawer</button>const [open, setOpen] = useState(false);
<NxButton onClick={() => setOpen(true)}>Open drawer</NxButton>
<NxDrawer open={open} onClose={() => setOpen(false)} title="Job filters">…</NxDrawer>API
React props (NxKit)
| Prop | Type | Default | Required | Description |
|---|---|---|---|---|
open | boolean | — | Required | Controls mount. |
onClose | ()=>void | undefined | Called on Esc, scrim click, or the close button. | |
side | "left"|"right" | "right" | Docks inline-end by default; "left" now means inline-start (flips under RTL). | |
title | ReactNode | undefined | Panel head title, wired to aria-labelledby. | |
footer | ReactNode | undefined | Panel foot content (usually actions). |
Classes
| Class | Description |
|---|---|
.nx-drawer | Fixed edge panel, shadow-overlay |
.nx-drawer--left | Docks inline-start (was literally left; now RTL-aware) |
.nx-panel__head/__body/__foot | Shared overlay chrome, also used by Modal |
Accessibility
- role="dialog" aria-modal="true"; focus moves to the first focusable (or the panel itself when it has no better target) on open, Tab/Shift+Tab wrap inside, Escape closes, and focus returns to the trigger on close (useFocusTrap).
- Body scroll is locked while open (useBodyScrollLock) so the page behind can't scroll.
Do / Don’t
- Do: Use for filters/secondary detail that doesn't need the user's full attention.Don’t: Don't nest a drawer inside a modal or vice versa.