Zero-dependency drawers for filters, carts and mobile nav — focus-trapped, scroll-locked, theme-aware. Click anything below — every card is live.
Right is the default; top/bottom take a height instead of a width.
Drawer.open({ side: 'left',
title: 'Navigation',
size: '320px' }) // width, or height
// for top/bottom
The hidden #cart-panel below this card is adopted into
the drawer and restored on close.
<button data-vdr-open="#cart-panel">
<div id="cart-panel" hidden
data-vdr-title="Your cart">…
// or: new Drawer('#cart-panel').open()
Same shape as Modal's buttons — close becomes the
onClose result; return false to stay open.
Drawer.open({
buttons: [
{ label: 'Reset', onClick: h => false },
{ label: 'Apply', variant: 'primary',
close: 'applied' }
],
onClose: r => r === 'applied' && apply()
})
No ✕, and Esc / backdrop clicks are ignored — only the button closes it.
Drawer.open({ dismissible: false,
buttons: [{ label: 'Done',
variant: 'primary', close: true }] })
Each drawer opens above the last; Esc peels only the top one.
// inside a button's onClick:
Drawer.open({ side: 'bottom', … })
return false // keep the first one open
With the VC core loaded, one call themes every component.
VC.config({ accent: '#b45309' })
Total $59