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
Show code Copy < nana-button onclick = " this . parentElement .querySelector ('nana-drawer') .show ()" >Open drawer</ nana-button >
< nana-drawer placement = "end" size = "md" label = "Filters" close-button >
< p style = "margin:0 0 1rem" >Refine your results.</ p >
< nana-input label = "Keyword" placeholder = "Search…" style = "width:100%" ></ nana-input >
< nana-button slot = "footer" variant = "ghost" onclick = " this .closest ('nana-drawer') .close ()" >Cancel</ nana-button >
< nana-button slot = "footer" variant = "primary" onclick = " this .closest ('nana-drawer') .close ()" >Apply</ nana-button >
</ nana-drawer >
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 () " >
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.
Show code Copy < nana-button onclick = " this . nextElementSibling .show ()" >Start</ nana-button >
< nana-drawer placement = "start" label = "Start" close-button >Slides from the start edge.</ nana-drawer >
< nana-button onclick = " this . nextElementSibling .show ()" >End</ nana-button >
< nana-drawer placement = "end" label = "End" close-button >Slides from the end edge.</ nana-drawer >
< nana-button onclick = " this . nextElementSibling .show ()" >Top</ nana-button >
< nana-drawer placement = "top" label = "Top" close-button >Slides from the top.</ nana-drawer >
< nana-button onclick = " this . nextElementSibling .show ()" >Bottom</ nana-button >
< nana-drawer placement = "bottom" label = "Bottom" close-button >Slides from the bottom.</ nana-drawer >
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.
Show code Copy < nana-button onclick = " this . nextElementSibling .show ()" >Small</ nana-button >
< nana-drawer placement = "end" size = "sm" label = "Small · 16rem" close-button >The small drawer.</ nana-drawer >
< nana-button onclick = " this . nextElementSibling .show ()" >Medium</ nana-button >
< nana-drawer placement = "end" size = "md" label = "Medium · 20rem" close-button >The default drawer.</ nana-drawer >
< nana-button onclick = " this . nextElementSibling .show ()" >Large</ nana-button >
< nana-drawer placement = "end" size = "lg" label = "Large · 28rem" close-button >The large drawer.</ nana-drawer >
< nana-button onclick = " this . nextElementSibling .show ()" >XL</ nana-button >
< nana-drawer placement = "end" size = "xl" label = "XL · 36rem" close-button >The extra-large drawer.</ nana-drawer >
< nana-button onclick = " this . nextElementSibling .show ()" >Full</ nana-button >
< nana-drawer placement = "end" size = "full" label = "Full · 100%" close-button >The full-size drawer.</ nana-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 >
< nana-button variant = " ghost " > Cancel </ nana-button >
< nana-button variant = " primary " > Save </ nana-button >
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 -->
Properties Property Attribute Type Default Description 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 label— string''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 open— booleanfalseWhether the drawer is open persistent— booleanfalsePersistent (non-modal, no backdrop) vs temporary (modal) placement— DrawerPlacement'end'Which edge the drawer slides from size— DrawerSize'md'Panel size — width (start/end) or height (top/bottom)
Events Event Description nana-openFired after opening nana-closeFired after closing
Slots Slot Description (default)Body content headerHeader content (overrides the `label` attribute) footerFooter actions
CSS parts Part Description ::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 Property Description --nana-drawer-sizePanel width (start/end) or height (top/bottom)
Method Description show()Open the drawer close()Close the drawer
Event Description nana-openFired after opening nana-closeFired after closing
Slot Description (default)Drawer body content headerCustom header (overrides the label attribute) footerFooter actions, pinned to the bottom
Variable Description --nana-drawer-sizePanel width (start/end) or height (top/bottom)
Part Description 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