# Drawer Drawer component for creating off-canvas side panels with overlay and toggle functionality. ## Tag `Drawer` ## Props | Prop | Type | Default | Description | | :--- | :--- | :--- | :--- | | `id` | `string` | Required | Unique identifier for the drawer | | `open` | `boolean \| Signal` | `false` | Drawer open state | | `side` | `VNode` | Required | Content to display in the drawer panel | | `content` | `VNode` | Required | Main page content | | `class` | `string` | `''` | Additional CSS classes (DaisyUI + Tailwind) | ## Styling Drawer supports all **daisyUI Drawer classes**: | Category | Keywords | Description | | :--- | :--- | :--- | | Position | `drawer-end` | Drawer opens from the right side | | Width | `w-64`, `w-80`, `w-96` | Custom drawer width (Tailwind) | > For further details, check the [daisyUI Drawer Documentation](https://daisyui.com/components/drawer) – Full reference for CSS classes. ## Live Examples ### Basic Drawer

Live Demo

```javascript const BasicDemo = () => { const isOpen = $(false); return Drawer({ id: 'basic-drawer', open: isOpen, side: div({ class: 'p-4' }, [ div({ class: 'text-lg font-bold mb-4' }, 'Menu'), div({ class: 'flex flex-col gap-2' }, [ button({ class: 'btn btn-ghost justify-start' }, 'Home'), button({ class: 'btn btn-ghost justify-start' }, 'About'), button({ class: 'btn btn-ghost justify-start' }, 'Contact') ]) ]), content: div({ class: 'p-4 text-center' }, [ button({ class: 'btn btn-primary', onclick: () => isOpen(true) }, 'Open Drawer') ]) }); }; mount(BasicDemo, '#demo-basic'); ``` ### Navigation Drawer

Live Demo

```javascript const NavDrawer = () => { const isOpen = $(false); const activePage = $('home'); const pages = { home: 'Welcome to the Home Page!', about: 'About Us - Learn more about our company', services: 'Our Services - What we offer', contact: 'Contact Us - Get in touch' }; return Drawer({ id: 'nav-drawer', open: isOpen, side: div({ class: 'p-4 w-64' }, [ div({ class: 'text-xl font-bold mb-6' }, 'MyApp'), div({ class: 'flex flex-col gap-1' }, [ button({ class: `btn btn-ghost justify-start ${activePage() === 'home' ? 'btn-active' : ''}`, onclick: () => { activePage('home'); isOpen(false); } }, '🏠 Home'), button({ class: `btn btn-ghost justify-start ${activePage() === 'about' ? 'btn-active' : ''}`, onclick: () => { activePage('about'); isOpen(false); } }, 'â„šī¸ About'), button({ class: `btn btn-ghost justify-start ${activePage() === 'services' ? 'btn-active' : ''}`, onclick: () => { activePage('services'); isOpen(false); } }, 'âš™ī¸ Services'), button({ class: `btn btn-ghost justify-start ${activePage() === 'contact' ? 'btn-active' : ''}`, onclick: () => { activePage('contact'); isOpen(false); } }, '📧 Contact') ]) ]), content: div({ class: 'p-4' }, [ div({ class: 'flex justify-between items-center mb-4' }, [ button({ class: 'btn btn-ghost btn-circle', onclick: () => isOpen(true) }, '☰'), span({ class: 'text-lg font-bold' }, 'MyApp') ]), div({ class: 'card bg-base-200 shadow-lg' }, [ div({ class: 'card-body' }, [ div({ class: 'text-2xl font-bold mb-2' }, () => activePage().charAt(0).toUpperCase() + activePage().slice(1)), div({ class: 'text-lg' }, () => pages[activePage()]) ]) ]) ]) }); }; mount(NavDrawer, '#demo-nav'); ``` ### Settings Drawer

Live Demo

```javascript const SettingsDrawer = () => { const isOpen = $(false); const darkMode = $(false); const notifications = $(true); const autoSave = $(false); return Drawer({ id: 'settings-drawer', open: isOpen, side: div({ class: 'p-4 w-80' }, [ div({ class: 'flex justify-between items-center mb-6' }, [ span({ class: 'text-xl font-bold' }, 'Settings'), button({ class: 'btn btn-ghost btn-circle btn-sm', onclick: () => isOpen(false) }, '✕') ]), div({ class: 'flex flex-col gap-4' }, [ div({ class: 'flex justify-between items-center' }, [ span({}, 'Dark Mode'), Swap({ value: darkMode, on: "🌙", off: "â˜€ī¸", onclick: () => darkMode(!darkMode()) }) ]), div({ class: 'flex justify-between items-center' }, [ span({}, 'Notifications'), Swap({ value: notifications, on: "🔔", off: "🔕", onclick: () => notifications(!notifications()) }) ]), div({ class: 'flex justify-between items-center' }, [ span({}, 'Auto Save'), Swap({ value: autoSave, on: "✅", off: "⭕", onclick: () => autoSave(!autoSave()) }) ]) ]), div({ class: 'divider my-4' }), div({ class: 'flex gap-2' }, [ button({ class: 'btn btn-primary flex-1', onclick: () => { isOpen(false); Toast('Settings saved!', 'alert-success', 2000); } }, 'Save'), button({ class: 'btn btn-ghost flex-1', onclick: () => isOpen(false) }, 'Cancel') ]) ]), content: div({ class: 'p-4' }, [ div({ class: 'flex justify-between items-center' }, [ span({ class: 'text-lg font-bold' }, 'Dashboard'), button({ class: 'btn btn-ghost btn-circle', onclick: () => isOpen(true) }, 'âš™ī¸') ]), div({ class: 'mt-4 grid grid-cols-2 gap-4' }, [ div({ class: 'stat bg-base-200 rounded-lg p-4' }, [ div({ class: 'stat-title' }, 'Users'), div({ class: 'stat-value' }, '1,234') ]), div({ class: 'stat bg-base-200 rounded-lg p-4' }, [ div({ class: 'stat-title' }, 'Revenue'), div({ class: 'stat-value' }, '$45K') ]) ]) ]) }); }; mount(SettingsDrawer, '#demo-settings'); ``` ### Cart Drawer

Live Demo

```javascript const CartDrawer = () => { const isOpen = $(false); const cart = $([ { id: 1, name: 'Product 1', price: 29, quantity: 2 }, { id: 2, name: 'Product 2', price: 49, quantity: 1 } ]); const updateQuantity = (id, delta) => { cart(cart().map(item => { if (item.id === id) { const newQty = Math.max(0, item.quantity + delta); return newQty === 0 ? null : { ...item, quantity: newQty }; } return item; }).filter(Boolean)); }; const total = () => cart().reduce((sum, item) => sum + (item.price * item.quantity), 0); return Drawer({ id: 'cart-drawer', open: isOpen, side: div({ class: 'flex flex-col h-full' }, [ div({ class: 'p-4 border-b border-base-300' }, [ div({ class: 'flex justify-between items-center' }, [ span({ class: 'text-xl font-bold' }, `Cart (${cart().length} items)`), button({ class: 'btn btn-ghost btn-circle btn-sm', onclick: () => isOpen(false) }, span('✕')) ]) ]), div({ class: 'flex-1 overflow-y-auto p-4' }, cart().length === 0 ? div({ class: 'text-center text-gray-500 mt-8' }, 'Your cart is empty') : div({ class: 'flex flex-col gap-3' }, cart().map(item => div({ class: 'flex gap-3 items-center p-2 bg-base-200 rounded-lg' }, [ div({ class: 'flex-1' }, [ div({ class: 'font-medium' }, item.name), div({ class: 'text-sm' }, `$${item.price} each`) ]), div({ class: 'flex items-center gap-2' }, [ button({ class: 'btn btn-xs btn-circle', onclick: () => updateQuantity(item.id, -1) }, span('-')), span({ class: 'w-8 text-center' }, item.quantity), button({ class: 'btn btn-xs btn-circle', onclick: () => updateQuantity(item.id, 1) }, span('+')) ]), span({ class: 'font-bold w-16 text-right' }, `$${item.price * item.quantity}`) ]) )) ), div({ class: 'p-4 border-t border-base-300' }, [ div({ class: 'flex justify-between items-center mb-4' }, [ span({ class: 'font-bold' }, 'Total'), span({ class: 'text-xl font-bold' }, () => `$${total()}`) ]), button({ class: 'btn btn-primary w-full', onclick: () => { isOpen(false); Toast('Checkout initiated!', 'alert-success', 2000); }, disabled: () => cart().length === 0 }, span('Checkout')) ]) ]), content: div({ class: 'p-4' }, [ div({ class: 'flex justify-between items-center' }, [ span({ class: 'text-lg font-bold' }, 'Store'), button({ class: 'btn btn-primary', onclick: () => isOpen(true) }, span({ class: 'flex items-center gap-2' }, [span('🛒'), span(`Cart (${cart().length})`)])) ]), div({ class: 'mt-4 grid grid-cols-2 gap-4' }, [ button({ class: 'btn btn-outline h-32 flex flex-col', onclick: () => { cart([...cart(), { id: Date.now(), name: 'New Product', price: 39, quantity: 1 }]); Toast('Added to cart!', 'alert-success', 1500); } }, span({ class: 'flex flex-col items-center gap-1' }, [span('đŸ“Ļ'), span('Add to Cart')])) ]) ]) }); }; mount(CartDrawer, '#demo-cart'); ``` ### Responsive Drawer

Live Demo

```javascript const ResponsiveDrawer = () => { const isOpen = $(false); const activePage = $('home'); const MenuItems = () => div({ class: 'flex flex-col gap-1 p-4' }, [ button({ class: `btn btn-ghost justify-start ${activePage() === 'home' ? 'btn-active' : ''}`, onclick: () => { activePage('home'); if (window.innerWidth < 1024) isOpen(false); } }, '🏠 Home'), button({ class: `btn btn-ghost justify-start ${activePage() === 'analytics' ? 'btn-active' : ''}`, onclick: () => { activePage('analytics'); if (window.innerWidth < 1024) isOpen(false); } }, '📊 Analytics'), button({ class: `btn btn-ghost justify-start ${activePage() === 'settings' ? 'btn-active' : ''}`, onclick: () => { activePage('settings'); if (window.innerWidth < 1024) isOpen(false); } }, 'âš™ī¸ Settings') ]); return Drawer({ id: 'responsive-drawer', open: isOpen, side: div({ class: 'w-64' }, [ div({ class: 'text-xl font-bold p-4 border-b border-base-300' }, 'Menu'), MenuItems() ]), content: div({ class: 'flex' }, [ div({ class: 'hidden lg:block w-64 border-r border-base-300' }, [MenuItems()]), div({ class: 'flex-1 p-4' }, [ div({ class: 'flex justify-between items-center lg:hidden mb-4' }, [ button({ class: 'btn btn-ghost btn-circle', onclick: () => isOpen(true) }, '☰'), span({ class: 'text-lg font-bold' }, 'MyApp') ]), div({ class: 'card bg-base-200' }, [ div({ class: 'card-body' }, [ div({ class: 'text-2xl font-bold' }, () => activePage().charAt(0).toUpperCase() + activePage().slice(1)), div({}, 'Content area. On desktop, the menu is always visible on the left.') ]) ]) ]) ]) }); }; mount(ResponsiveDrawer, '#demo-responsive'); ``` ### Form Drawer

Live Demo

```javascript const FormDrawer = () => { const isOpen = $(false); const name = $(''); const email = $(''); const message = $(''); const handleSubmit = () => { if (name() && email() && message()) { Toast('Message sent!', 'alert-success', 2000); isOpen(false); name(''); email(''); message(''); } else { Toast('Please fill all fields', 'alert-warning', 2000); } }; return Drawer({ id: 'form-drawer', open: isOpen, side: div({ class: 'p-4 w-96' }, [ div({ class: 'flex justify-between items-center mb-4' }, [ span({ class: 'text-xl font-bold' }, 'Contact Us'), button({ class: 'btn btn-ghost btn-circle btn-sm', onclick: () => isOpen(false) }, '✕') ]), div({ class: 'flex flex-col gap-4' }, [ input({ label: 'Name', value: name, placeholder: 'Your name', oninput: (e) => name(e.target.value) }), input({ label: 'Email', type: 'email', value: email, placeholder: 'your@email.com', oninput: (e) => email(e.target.value) }), div({ class: 'form-control' }, [ span({ class: 'label-text mb-1' }, 'Message'), h('textarea', { class: 'textarea textarea-bordered h-24', placeholder: 'Your message', value: message, oninput: (e) => message(e.target.value) }) ]), div({ class: 'flex gap-2 mt-2' }, [ button({ class: 'btn btn-primary flex-1', onclick: handleSubmit }, 'Send'), button({ class: 'btn btn-ghost flex-1', onclick: () => isOpen(false) }, 'Cancel') ]) ]) ]), content: div({ class: 'p-4 text-center' }, [ button({ class: 'btn btn-primary', onclick: () => isOpen(true) }, 'Contact Us') ]) }); }; mount(FormDrawer, '#demo-form'); ```