Components / Overlays & Dialogs / Drawer
Drawer beta
A panel that slides in from the edge — detail and forms without losing the page.
Uses: Button — include its CSS alongside this one.
<button class="btn btn-pri btn-md" data-drawer-open>Open drawer</button>
<dialog class="kdrawer" data-drawer aria-label="Invoice detail">
<div class="kdrawer-head">
<div class="kdrawer-title">Invoice INV-1042</div>
<button class="btn btn-ghost btn-sm" data-drawer-close aria-label="Close"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 6l12 12M18 6 6 18"/></svg></button>
</div>
<div class="kdrawer-body">Issued on the 1st, due at the end of the month. Two line items, both confirmed by the client. The full breakdown and the payment link live here, next to the list they came from.</div>
<div class="kdrawer-foot">
<button class="btn btn-sec btn-md" data-drawer-close>Close</button>
<button class="btn btn-pri btn-md" data-drawer-close>Send reminder</button>
</div>
</dialog>.kdrawer{border:0;padding:0;margin:0 0 0 auto;inset:0 0 0 auto;position:fixed;height:100dvh;max-height:100dvh;width:min(360px,92vw);background:var(--k-bg);color:var(--k-ink);font-family:var(--k-font);box-shadow:-24px 0 60px -24px rgba(0,0,0,.35)}
.kdrawer::backdrop{background:rgba(24,24,27,.45);backdrop-filter:blur(3px)}
.kdrawer[open]{animation:kdrawer-in var(--k-dur-2) var(--k-ease)}
@keyframes kdrawer-in{from{transform:translateX(36px);opacity:.4}to{transform:none;opacity:1}}
@media (prefers-reduced-motion:reduce){.kdrawer[open]{animation:none}}
.kdrawer-head{display:flex;align-items:center;justify-content:space-between;padding:18px 20px;border-bottom:1px solid var(--k-line)}
.kdrawer-title{font-size:15px;font-weight:600}
.kdrawer-body{padding:20px;font-size:13.5px;line-height:1.85;color:var(--k-ink-2)}
.kdrawer-foot{display:flex;gap:9px;justify-content:flex-end;padding:16px 20px;border-top:1px solid var(--k-line)}
const drawer = document.querySelector('[data-drawer]');
document.querySelector('[data-drawer-open]').addEventListener('click', () => drawer.showModal());
drawer.querySelectorAll('[data-drawer-close]').forEach(b => b.addEventListener('click', () => drawer.close()));
Usage
For detail views and edit forms that belong to the current page. On narrow screens it takes most of the width.
Accessibility
Built on <dialog>: focus is trapped and Escape closes. The close button is labelled, not just an icon.
Related parts
Alert Dialog beta
The decision that cannot be clicked away — for destructive, irreversible actions.
Command beta
The ⌘K palette: one input that searches actions and pages, driven from the keyboard.
Context Menu beta
The right-click menu, written as a component instead of an accident of the browser.
Dropdown stable
Opens with a soft scale. Headings, dividers and a red danger item included.