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

24 KiB

Menu

Menu component for creating navigation menus, sidebars, and dropdowns with support for nested items, icons, and active states.

Tag

Menu

Props

Prop Type Default Description
items Array<MenuItem> [] Menu items configuration
class string '' Additional CSS classes (DaisyUI + Tailwind)

MenuItem Structure

Property Type Description
label string | VNode Menu item text or content
icon string | VNode Optional icon to display
active boolean | Signal<boolean> Active state highlighting
onclick function Click handler
children Array<MenuItem> Nested submenu items
open boolean Whether submenu is open (for nested items)

Live Examples

Basic Menu

Live Demo

const BasicDemo = () => {
  const activeItem = $('home');
  
  return Menu({
    items: [
      { 
        label: 'Home', 
        active: () => activeItem() === 'home',
        onclick: () => activeItem('home')
      },
      { 
        label: 'About', 
        active: () => activeItem() === 'about',
        onclick: () => activeItem('about')
      },
      { 
        label: 'Contact', 
        active: () => activeItem() === 'contact',
        onclick: () => activeItem('contact')
      }
    ]
  });
};
Mount(BasicDemo, '#demo-basic');

With Icons

Live Demo

const IconsDemo = () => {
  const activeItem = $('dashboard');
  
  return Menu({
    items: [
      { 
        icon: '🏠', 
        label: 'Dashboard',
        active: () => activeItem() === 'dashboard',
        onclick: () => activeItem('dashboard')
      },
      { 
        icon: '📊', 
        label: 'Analytics',
        active: () => activeItem() === 'analytics',
        onclick: () => activeItem('analytics')
      },
      { 
        icon: '⚙️', 
        label: 'Settings',
        active: () => activeItem() === 'settings',
        onclick: () => activeItem('settings')
      },
      { 
        icon: '👤', 
        label: 'Profile',
        active: () => activeItem() === 'profile',
        onclick: () => activeItem('profile')
      }
    ]
  });
};
Mount(IconsDemo, '#demo-icons');

Nested Menu

Live Demo

const NestedDemo = () => {
  const activeItem = $('products');
  
  return Menu({
    items: [
      { 
        label: 'Dashboard',
        onclick: () => activeItem('dashboard'),
        active: () => activeItem() === 'dashboard'
      },
      { 
        label: 'Products',
        icon: '📦',
        open: true,
        children: [
          { 
            label: 'All Products',
            onclick: () => activeItem('all-products'),
            active: () => activeItem() === 'all-products'
          },
          { 
            label: 'Add New',
            onclick: () => activeItem('add-product'),
            active: () => activeItem() === 'add-product'
          },
          { 
            label: 'Categories',
            children: [
              { 
                label: 'Electronics',
                onclick: () => activeItem('electronics'),
                active: () => activeItem() === 'electronics'
              },
              { 
                label: 'Clothing',
                onclick: () => activeItem('clothing'),
                active: () => activeItem() === 'clothing'
              }
            ]
          }
        ]
      },
      { 
        label: 'Orders',
        icon: '📋',
        onclick: () => activeItem('orders'),
        active: () => activeItem() === 'orders'
      },
      { 
        label: 'Settings',
        icon: '⚙️',
        onclick: () => activeItem('settings'),
        active: () => activeItem() === 'settings'
      }
    ]
  });
};
Mount(NestedDemo, '#demo-nested');

Horizontal Menu

Live Demo

const HorizontalDemo = () => {
  const activeItem = $('home');
  
  return Menu({
    class: 'menu-horizontal rounded-box',
    items: [
      { 
        label: 'Home',
        active: () => activeItem() === 'home',
        onclick: () => activeItem('home')
      },
      { 
        label: 'Products',
        children: [
          { label: 'Electronics', onclick: () => activeItem('electronics') },
          { label: 'Clothing', onclick: () => activeItem('clothing') },
          { label: 'Books', onclick: () => activeItem('books') }
        ]
      },
      { 
        label: 'About',
        onclick: () => activeItem('about'),
        active: () => activeItem() === 'about'
      },
      { 
        label: 'Contact',
        onclick: () => activeItem('contact'),
        active: () => activeItem() === 'contact'
      }
    ]
  });
};
Mount(HorizontalDemo, '#demo-horizontal');

Sidebar Menu

Live Demo

const SidebarDemo = () => {
  const activeItem = $('dashboard');
  
  return Div({ class: 'flex' }, [
    Div({ class: 'w-64' }, [
      Menu({
        class: 'rounded-box w-full',
        items: [
          { 
            icon: '📊', 
            label: 'Dashboard',
            active: () => activeItem() === 'dashboard',
            onclick: () => activeItem('dashboard')
          },
          { 
            icon: '👥', 
            label: 'Users',
            children: [
              { 
                label: 'All Users',
                onclick: () => activeItem('all-users'),
                active: () => activeItem() === 'all-users'
              },
              { 
                label: 'Add User',
                onclick: () => activeItem('add-user'),
                active: () => activeItem() === 'add-user'
              }
            ]
          },
          { 
            icon: '📁', 
            label: 'Files',
            onclick: () => activeItem('files'),
            active: () => activeItem() === 'files'
          },
          { 
            icon: '⚙️', 
            label: 'Settings',
            onclick: () => activeItem('settings'),
            active: () => activeItem() === 'settings'
          }
        ]
      })
    ]),
    Div({ class: 'flex-1 p-4' }, [
      Div({ class: 'alert alert-info' }, () => `Current page: ${activeItem()}`)
    ])
  ]);
};
Mount(SidebarDemo, '#demo-sidebar');

Account Menu

Live Demo

const AccountDemo = () => {
  const [notifications, setNotifications] = $(3);
  
  return Menu({
    class: 'rounded-box w-56',
    items: [
      { 
        icon: '👤', 
        label: 'My Profile',
        onclick: () => Toast('Profile clicked', 'alert-info', 2000)
      },
      { 
        icon: '📧', 
        label: 'Messages',
        badge: '3',
        onclick: () => Toast('Messages opened', 'alert-info', 2000)
      },
      { 
        icon: '🔔', 
        label: 'Notifications',
        badge: () => notifications(),
        onclick: () => {
          setNotifications(0);
          Toast('Notifications cleared', 'alert-success', 2000);
        }
      },
      { 
        icon: '⚙️', 
        label: 'Settings',
        onclick: () => Toast('Settings opened', 'alert-info', 2000)
      },
      { 
        icon: '🚪', 
        label: 'Logout',
        onclick: () => Toast('Logged out', 'alert-warning', 2000)
      }
    ]
  });
};
Mount(AccountDemo, '#demo-account');

Collapsible Sidebar

Live Demo

const CollapsibleDemo = () => {
  const collapsed = $(false);
  const activeItem = $('dashboard');
  
  return Div({ class: 'flex gap-4' }, [
    Div({ class: `transition-all duration-300 ${collapsed() ? 'w-16' : 'w-64'}` }, [
      Button({ 
        class: 'btn btn-ghost btn-sm mb-2 w-full',
        onclick: () => collapsed(!collapsed())
      }, collapsed() ? '→' : '←'),
      Menu({
        class: `rounded-box ${collapsed() ? 'menu-compact' : ''}`,
        items: [
          { icon: '📊', label: collapsed() ? '' : 'Dashboard', active: () => activeItem() === 'dashboard', onclick: () => activeItem('dashboard') },
          { icon: '👥', label: collapsed() ? '' : 'Users', active: () => activeItem() === 'users', onclick: () => activeItem('users') },
          { icon: '📁', label: collapsed() ? '' : 'Files', active: () => activeItem() === 'files', onclick: () => activeItem('files') },
          { icon: '⚙️', label: collapsed() ? '' : 'Settings', active: () => activeItem() === 'settings', onclick: () => activeItem('settings') }
        ]
      })
    ]),
    Div({ class: 'flex-1' }, [
      Div({ class: 'alert alert-info' }, () => `Selected: ${activeItem()}`)
    ])
  ]);
};
Mount(CollapsibleDemo, '#demo-collapsible');

All Variants

Live Demo

const VariantsDemo = () => {
  const items = [
    { label: 'Item 1' },
    { label: 'Item 2' },
    { label: 'Item 3', children: [
      { label: 'Subitem 1' },
      { label: 'Subitem 2' }
    ]}
  ];
  
  return Div({ class: 'flex flex-wrap gap-8' }, [
    Div({ class: 'w-48' }, [
      Div({ class: 'text-sm font-bold mb-2' }, 'Default'),
      Menu({ items })
    ]),
    Div({ class: 'w-48' }, [
      Div({ class: 'text-sm font-bold mb-2' }, 'Compact'),
      Menu({ items, class: 'menu-compact' })
    ]),
    Div({ class: 'w-48' }, [
      Div({ class: 'text-sm font-bold mb-2' }, 'With Shadow'),
      Menu({ items, class: 'shadow-lg' })
    ])
  ]);
};
Mount(VariantsDemo, '#demo-variants');
<script> (function() { const initMenuExamples = () => { // 1. Basic Menu const basicTarget = document.querySelector('#demo-basic'); if (basicTarget && !basicTarget.hasChildNodes()) { const BasicDemo = () => { const activeItem = $('home'); return Menu({ items: [ { label: 'Home', active: () => activeItem() === 'home', onclick: () => activeItem('home') }, { label: 'About', active: () => activeItem() === 'about', onclick: () => activeItem('about') }, { label: 'Contact', active: () => activeItem() === 'contact', onclick: () => activeItem('contact') } ] }); }; Mount(BasicDemo, basicTarget); } // 2. With Icons const iconsTarget = document.querySelector('#demo-icons'); if (iconsTarget && !iconsTarget.hasChildNodes()) { const IconsDemo = () => { const activeItem = $('dashboard'); return Menu({ items: [ { icon: '🏠', label: 'Dashboard', active: () => activeItem() === 'dashboard', onclick: () => activeItem('dashboard') }, { icon: '📊', label: 'Analytics', active: () => activeItem() === 'analytics', onclick: () => activeItem('analytics') }, { icon: '⚙️', label: 'Settings', active: () => activeItem() === 'settings', onclick: () => activeItem('settings') }, { icon: '👤', label: 'Profile', active: () => activeItem() === 'profile', onclick: () => activeItem('profile') } ] }); }; Mount(IconsDemo, iconsTarget); } // 3. Nested Menu const nestedTarget = document.querySelector('#demo-nested'); if (nestedTarget && !nestedTarget.hasChildNodes()) { const NestedDemo = () => { const activeItem = $('products'); return Menu({ items: [ { label: 'Dashboard', onclick: () => activeItem('dashboard'), active: () => activeItem() === 'dashboard' }, { label: 'Products', icon: '📦', open: true, children: [ { label: 'All Products', onclick: () => activeItem('all-products'), active: () => activeItem() === 'all-products' }, { label: 'Add New', onclick: () => activeItem('add-product'), active: () => activeItem() === 'add-product' }, { label: 'Categories', children: [ { label: 'Electronics', onclick: () => activeItem('electronics'), active: () => activeItem() === 'electronics' }, { label: 'Clothing', onclick: () => activeItem('clothing'), active: () => activeItem() === 'clothing' } ] } ] }, { label: 'Orders', icon: '📋', onclick: () => activeItem('orders'), active: () => activeItem() === 'orders' }, { label: 'Settings', icon: '⚙️', onclick: () => activeItem('settings'), active: () => activeItem() === 'settings' } ] }); }; Mount(NestedDemo, nestedTarget); } // 4. Horizontal Menu const horizontalTarget = document.querySelector('#demo-horizontal'); if (horizontalTarget && !horizontalTarget.hasChildNodes()) { const HorizontalDemo = () => { const activeItem = $('home'); return Menu({ class: 'menu-horizontal rounded-box', items: [ { label: 'Home', active: () => activeItem() === 'home', onclick: () => activeItem('home') }, { label: 'Products', children: [ { label: 'Electronics', onclick: () => activeItem('electronics') }, { label: 'Clothing', onclick: () => activeItem('clothing') }, { label: 'Books', onclick: () => activeItem('books') } ] }, { label: 'About', onclick: () => activeItem('about'), active: () => activeItem() === 'about' }, { label: 'Contact', onclick: () => activeItem('contact'), active: () => activeItem() === 'contact' } ] }); }; Mount(HorizontalDemo, horizontalTarget); } // 5. Sidebar Menu const sidebarTarget = document.querySelector('#demo-sidebar'); if (sidebarTarget && !sidebarTarget.hasChildNodes()) { const SidebarDemo = () => { const activeItem = $('dashboard'); return Div({ class: 'flex' }, [ Div({ class: 'w-64' }, [ Menu({ class: 'rounded-box w-full', items: [ { icon: '📊', label: 'Dashboard', active: () => activeItem() === 'dashboard', onclick: () => activeItem('dashboard') }, { icon: '👥', label: 'Users', children: [ { label: 'All Users', onclick: () => activeItem('all-users'), active: () => activeItem() === 'all-users' }, { label: 'Add User', onclick: () => activeItem('add-user'), active: () => activeItem() === 'add-user' } ] }, { icon: '📁', label: 'Files', onclick: () => activeItem('files'), active: () => activeItem() === 'files' }, { icon: '⚙️', label: 'Settings', onclick: () => activeItem('settings'), active: () => activeItem() === 'settings' } ] }) ]), Div({ class: 'flex-1 p-4' }, [ Div({ class: 'alert alert-info' }, () => `Current page: ${activeItem()}`) ]) ]); }; Mount(SidebarDemo, sidebarTarget); } // 6. Account Menu const accountTarget = document.querySelector('#demo-account'); if (accountTarget && !accountTarget.hasChildNodes()) { const AccountDemo = () => { const [notifications, setNotifications] = $(3); return Menu({ class: 'rounded-box w-56', items: [ { icon: '👤', label: 'My Profile', onclick: () => Toast('Profile clicked', 'alert-info', 2000) }, { icon: '📧', label: 'Messages', badge: '3', onclick: () => Toast('Messages opened', 'alert-info', 2000) }, { icon: '🔔', label: 'Notifications', badge: () => notifications(), onclick: () => { setNotifications(0); Toast('Notifications cleared', 'alert-success', 2000); } }, { icon: '⚙️', label: 'Settings', onclick: () => Toast('Settings opened', 'alert-info', 2000) }, { icon: '🚪', label: 'Logout', onclick: () => Toast('Logged out', 'alert-warning', 2000) } ] }); }; Mount(AccountDemo, accountTarget); } // 7. Collapsible Sidebar const collapsibleTarget = document.querySelector('#demo-collapsible'); if (collapsibleTarget && !collapsibleTarget.hasChildNodes()) { const CollapsibleDemo = () => { const collapsed = $(false); const activeItem = $('dashboard'); return Div({ class: 'flex gap-4' }, [ Div({ class: `transition-all duration-300 ${collapsed() ? 'w-16' : 'w-64'}` }, [ Button({ class: 'btn btn-ghost btn-sm mb-2 w-full', onclick: () => collapsed(!collapsed()) }, collapsed() ? '→' : '←'), Menu({ class: `rounded-box ${collapsed() ? 'menu-compact' : ''}`, items: [ { icon: '📊', label: collapsed() ? '' : 'Dashboard', active: () => activeItem() === 'dashboard', onclick: () => activeItem('dashboard') }, { icon: '👥', label: collapsed() ? '' : 'Users', active: () => activeItem() === 'users', onclick: () => activeItem('users') }, { icon: '📁', label: collapsed() ? '' : 'Files', active: () => activeItem() === 'files', onclick: () => activeItem('files') }, { icon: '⚙️', label: collapsed() ? '' : 'Settings', active: () => activeItem() === 'settings', onclick: () => activeItem('settings') } ] }) ]), Div({ class: 'flex-1' }, [ Div({ class: 'alert alert-info' }, () => `Selected: ${activeItem()}`) ]) ]); }; Mount(CollapsibleDemo, collapsibleTarget); } // 8. All Variants const variantsTarget = document.querySelector('#demo-variants'); if (variantsTarget && !variantsTarget.hasChildNodes()) { const VariantsDemo = () => { const items = [ { label: 'Item 1' }, { label: 'Item 2' }, { label: 'Item 3', children: [ { label: 'Subitem 1' }, { label: 'Subitem 2' } ]} ]; return Div({ class: 'flex flex-wrap gap-8' }, [ Div({ class: 'w-48' }, [ Div({ class: 'text-sm font-bold mb-2' }, 'Default'), Menu({ items }) ]), Div({ class: 'w-48' }, [ Div({ class: 'text-sm font-bold mb-2' }, 'Compact'), Menu({ items, class: 'menu-compact' }) ]), Div({ class: 'w-48' }, [ Div({ class: 'text-sm font-bold mb-2' }, 'With Shadow'), Menu({ items, class: 'shadow-lg' }) ]) ]); }; Mount(VariantsDemo, variantsTarget); } }; initMenuExamples(); if (window.$docsify) { window.$docsify.plugins = [].concat(window.$docsify.plugins || [], (hook) => { hook.doneEach(initMenuExamples); }); } })(); </script>