Files
sigpro-ui/docs/components_old/drawer.md
2026-04-06 03:19:15 +02:00

32 KiB
Raw Blame History

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<boolean> 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)

Live Examples

Basic Drawer

Live Demo

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

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

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

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

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

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');
<script> (function() { const initDrawerExamples = () => { // 1. Basic Drawer const basicTarget = document.querySelector('#demo-basic'); if (basicTarget && !basicTarget.hasChildNodes()) { 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, basicTarget); } // 2. Navigation Drawer const navTarget = document.querySelector('#demo-nav'); if (navTarget && !navTarget.hasChildNodes()) { 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, navTarget); } // 3. Settings Drawer const settingsTarget = document.querySelector('#demo-settings'); if (settingsTarget && !settingsTarget.hasChildNodes()) { 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, settingsTarget); } // 4. Cart Drawer const cartTarget = document.querySelector('#demo-cart'); if (cartTarget && !cartTarget.hasChildNodes()) { 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, cartTarget); } // 5. Responsive Drawer const responsiveTarget = document.querySelector('#demo-responsive'); if (responsiveTarget && !responsiveTarget.hasChildNodes()) { 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, responsiveTarget); } // 6. Form Drawer const formTarget = document.querySelector('#demo-form'); if (formTarget && !formTarget.hasChildNodes()) { 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, formTarget); } }; initDrawerExamples(); if (window.$docsify) { window.$docsify.plugins = [].concat(window.$docsify.plugins || [], (hook) => { hook.doneEach(initDrawerExamples); }); } })(); </script>