# 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) }, '✕') ]) ]), 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({ class: 'w-8 text-center' }, item.quantity), Button({ class: 'btn btn-xs btn-circle', onclick: () => updateQuantity(item.id, 1) }, '+') ]), 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 }, '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) }, () => `🛒 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); } }, ['đŸ“Ļ', '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'), Tag('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'); ```