Skip to content
Nana UI

Drawer

View .md Download

A panel that slides in from an edge, built on the native <dialog> element. temporary (default) shows a modal with a backdrop and focus trap; persistent shows a non-modal panel that doesn’t block the page.

Click to open. The drawer is a native modal — backdrop, focus trap, and closes on Esc, backdrop click, or the close button.

Open drawer

Refine your results.

Cancel Apply
Terminal window
npm install @nana-tec/ui-components
import "@nana-tec/ui-components/drawer";

Open with the open attribute or .show(); close with .close(), the close button, backdrop click, or Esc.

<nana-button onclick="document.getElementById('d').show()">Open</nana-button>
<nana-drawer id="d" placement="end" label="Settings" close-button>
<p>Drawer body content.</p>
<nana-button slot="footer" variant="primary" onclick="document.getElementById('d').close()">
Save
</nana-button>
</nana-drawer>

The placement attribute picks the edge — start, end (default), top, or bottom.

Start Slides from the start edge. End Slides from the end edge. Top Slides from the top. Bottom Slides from the bottom.

size sets the panel’s width (start/end) or height (top/bottom): sm (16rem), md (20rem, default), lg (28rem), xl (36rem), or full (100%). Override any of them with --nana-drawer-size.

Small The small drawer. Medium The default drawer. Large The large drawer. XL The extra-large drawer. Full The full-size drawer.

Give it a title with label (and close-button for a built-in ✕), or take full control with the header and footer slots.

<nana-drawer placement="end" close-button>
<div slot="header">Custom header</div>
Body content…
<div slot="footer">
<nana-button variant="ghost">Cancel</nana-button>
<nana-button variant="primary">Save</nana-button>
</div>
</nana-drawer>

Add persistent for a non-modal panel that doesn’t dim or block the page — ideal for a filter rail or navigation that stays open alongside the content.

<nana-drawer placement="start" persistent open label="Filters">
<!-- stays open; the page remains interactive -->
</nana-drawer>

Properties

PropertyAttributeTypeDefaultDescription
ariaLabelaria-labelstring | nullnullAccessible label (falls back to `label`)
closeButtonclose-buttonbooleanfalseShow a built-in close button in the header
closeLabelclose-labelstring'Close'Accessible label for the close button
labelstring''Header title text (ignored when the `header` slot is used)
noBackdropCloseno-backdrop-closebooleanfalseDon't close on backdrop click (temporary only)
noEscapeCloseno-escape-closebooleanfalseDon't close on Escape
openbooleanfalseWhether the drawer is open
persistentbooleanfalsePersistent (non-modal, no backdrop) vs temporary (modal)
placementDrawerPlacement'end'Which edge the drawer slides from
sizeDrawerSize'md'Panel size — width (start/end) or height (top/bottom)

Events

EventDescription
nana-openFired after opening
nana-closeFired after closing

Slots

SlotDescription
(default)Body content
headerHeader content (overrides the `label` attribute)
footerFooter actions

CSS parts

PartDescription
::part(dialog)The native `<dialog>`
::part(panel)The sliding panel
::part(header)The header row
::part(close-button)The built-in close button

CSS custom properties

PropertyDescription
--nana-drawer-sizePanel width (start/end) or height (top/bottom)
MethodDescription
show()Open the drawer
close()Close the drawer
EventDescription
nana-openFired after opening
nana-closeFired after closing
SlotDescription
(default)Drawer body content
headerCustom header (overrides the label attribute)
footerFooter actions, pinned to the bottom
VariableDescription
--nana-drawer-sizePanel width (start/end) or height (top/bottom)
PartDescription
dialogThe native <dialog> element
panelThe sliding panel
headerThe header row
close-buttonThe built-in close button
  • Native dialog semantics
  • Focus trapped while open
  • Escape to close
  • Focus returns to trigger
  • WCAG 2.2 AA contrast
Explore Drawer interactively Every state, prop, and edge case — with live controls — in Storybook.
View in Storybook