Menubar
Horizontal menu bar with dropdown menus, like desktop application menus (File, Edit, View). Supports submenus, shortcuts, checkbox/radio items, and separators.
Basic Menubar
Preview
<nav class="menubar">
<div class="menubar-menu">
<button class="menubar-trigger" aria-expanded="true" data-state="open">File</button>
<div class="menubar-content" data-state="open">
<button class="menubar-item">
<span class="menubar-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" class="w-full h-full"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" /></svg></span>
New File
<span class="menubar-shortcut">⌘N</span>
</button>
<button class="menubar-item">
Open
<span class="menubar-shortcut">⌘O</span>
</button>
<div class="menubar-separator"></div>
<button class="menubar-item">
Save
<span class="menubar-shortcut">⌘S</span>
</button>
<button class="menubar-item">Save As...</button>
</div>
</div>
<div class="menubar-menu">
<button class="menubar-trigger">Edit</button>
</div>
<div class="menubar-menu">
<button class="menubar-trigger">View</button>
</div>
</nav> Requires: ux.min.css
<nav class="inline-flex items-center gap-0.5 h-9 p-0.5 bg-base-100 border border-base-300 rounded-box shadow-xs">
<div class="relative">
<button class="flex items-center justify-center px-2 py-1 text-sm font-medium bg-base-200 rounded-field border-none cursor-pointer" aria-expanded="true">File</button>
<div class="absolute top-full left-[-4px] mt-2 min-w-48 p-1 bg-base-100 border border-base-300 rounded-box shadow-lg z-100">
<button class="flex items-center gap-2 w-full px-2 py-1 text-sm bg-transparent border-none cursor-pointer rounded-field hover:bg-base-200 text-left" style="color: var(--color-base-content);">
<span class="shrink-0 size-4 opacity-60"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" class="w-full h-full"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" /></svg></span>
New File
<span class="ml-auto text-xs text-base-content/40 tracking-wide">⌘N</span>
</button>
<button class="flex items-center gap-2 w-full px-2 py-1 text-sm bg-transparent border-none cursor-pointer rounded-field hover:bg-base-200 text-left" style="color: var(--color-base-content);">
Open
<span class="ml-auto text-xs text-base-content/40 tracking-wide">⌘O</span>
</button>
<div class="h-px my-1 -mx-1 bg-base-300"></div>
<button class="flex items-center gap-2 w-full px-2 py-1 text-sm bg-transparent border-none cursor-pointer rounded-field hover:bg-base-200 text-left" style="color: var(--color-base-content);">
Save
<span class="ml-auto text-xs text-base-content/40 tracking-wide">⌘S</span>
</button>
<button class="flex items-center gap-2 w-full px-2 py-1 text-sm bg-transparent border-none cursor-pointer rounded-field hover:bg-base-200 text-left" style="color: var(--color-base-content);">Save As...</button>
</div>
</div>
<div class="relative">
<button class="flex items-center justify-center px-2 py-1 text-sm font-medium bg-transparent rounded-field border-none cursor-pointer hover:bg-base-200" style="color: var(--color-base-content);">Edit</button>
</div>
<div class="relative">
<button class="flex items-center justify-center px-2 py-1 text-sm font-medium bg-transparent rounded-field border-none cursor-pointer hover:bg-base-200" style="color: var(--color-base-content);">View</button>
</div>
</nav> Requires: tw.min.css
// Toggle menu on click:
document.querySelectorAll('.menubar-trigger').forEach(trigger => {
trigger.addEventListener('click', () => {
const content = trigger.nextElementSibling;
const isOpen = trigger.getAttribute('data-state') === 'open';
// Close all other menus first
document.querySelectorAll('.menubar-trigger[data-state="open"]').forEach(t => {
t.setAttribute('data-state', 'closed');
t.setAttribute('aria-expanded', 'false');
});
if (!isOpen) {
trigger.setAttribute('data-state', 'open');
trigger.setAttribute('aria-expanded', 'true');
}
});
}); With Submenu
Preview
<nav class="menubar">
<div class="menubar-menu">
<button class="menubar-trigger" data-state="open" aria-expanded="true">Edit</button>
<div class="menubar-content" data-state="open">
<button class="menubar-item">Undo <span class="menubar-shortcut">⌘Z</span></button>
<button class="menubar-item">Redo <span class="menubar-shortcut">⇧⌘Z</span></button>
<div class="menubar-separator"></div>
<div class="menubar-sub">
<button class="menubar-sub-trigger">
Find & Replace
<span class="menubar-sub-arrow"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" class="w-full h-full"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" /></svg></span>
</button>
<div class="menubar-sub-content" data-state="open">
<button class="menubar-item">Find <span class="menubar-shortcut">⌘F</span></button>
<button class="menubar-item">Replace <span class="menubar-shortcut">⌘H</span></button>
<button class="menubar-item">Find in Files</button>
</div>
</div>
<div class="menubar-separator"></div>
<button class="menubar-item">Select All <span class="menubar-shortcut">⌘A</span></button>
</div>
</div>
</nav> Requires: ux.min.css
<nav class="inline-flex items-center gap-0.5 h-9 p-0.5 bg-base-100 border border-base-300 rounded-box shadow-xs">
<div class="relative">
<button class="flex items-center justify-center px-2 py-1 text-sm font-medium bg-base-200 rounded-field border-none cursor-pointer">Edit</button>
<div class="absolute top-full left-[-4px] mt-2 min-w-48 p-1 bg-base-100 border border-base-300 rounded-box shadow-lg z-100">
<button class="flex items-center gap-2 w-full px-2 py-1 text-sm bg-transparent border-none cursor-pointer rounded-field hover:bg-base-200 text-left" style="color: var(--color-base-content);">Undo <span class="ml-auto text-xs text-base-content/40">⌘Z</span></button>
<button class="flex items-center gap-2 w-full px-2 py-1 text-sm bg-transparent border-none cursor-pointer rounded-field hover:bg-base-200 text-left" style="color: var(--color-base-content);">Redo <span class="ml-auto text-xs text-base-content/40">⇧⌘Z</span></button>
<div class="h-px my-1 -mx-1 bg-base-300"></div>
<div class="relative group">
<button class="flex items-center gap-2 w-full px-2 py-1 text-sm bg-transparent border-none cursor-pointer rounded-field hover:bg-base-200 text-left" style="color: var(--color-base-content);">
Find & Replace
<span class="ml-auto size-4 opacity-60"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" class="w-full h-full"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5" /></svg></span>
</button>
<div class="absolute left-full top-[-4px] ml-1 min-w-32 p-1 bg-base-100 border border-base-300 rounded-box shadow-lg z-100 hidden group-hover:block">
<button class="flex items-center gap-2 w-full px-2 py-1 text-sm bg-transparent border-none cursor-pointer rounded-field hover:bg-base-200 text-left" style="color: var(--color-base-content);">Find <span class="ml-auto text-xs text-base-content/40">⌘F</span></button>
<button class="flex items-center gap-2 w-full px-2 py-1 text-sm bg-transparent border-none cursor-pointer rounded-field hover:bg-base-200 text-left" style="color: var(--color-base-content);">Replace <span class="ml-auto text-xs text-base-content/40">⌘H</span></button>
<button class="flex items-center gap-2 w-full px-2 py-1 text-sm bg-transparent border-none cursor-pointer rounded-field hover:bg-base-200 text-left" style="color: var(--color-base-content);">Find in Files</button>
</div>
</div>
<div class="h-px my-1 -mx-1 bg-base-300"></div>
<button class="flex items-center gap-2 w-full px-2 py-1 text-sm bg-transparent border-none cursor-pointer rounded-field hover:bg-base-200 text-left" style="color: var(--color-base-content);">Select All <span class="ml-auto text-xs text-base-content/40">⌘A</span></button>
</div>
</div>
</nav> Requires: tw.min.css
// Submenu opens on hover by default (CSS).
// For keyboard navigation, toggle data-state on submenus:
// subTrigger.addEventListener('keydown', (e) => {
// if (e.key === 'ArrowRight') subContent.dataset.state = 'open';
// if (e.key === 'ArrowLeft') subContent.dataset.state = 'closed';
// }); Compact & Glass
Preview
<div class="flex flex-col gap-4">
<!-- Compact -->
<nav class="menubar menubar-compact">
<div class="menubar-menu">
<button class="menubar-trigger">File</button>
</div>
<div class="menubar-menu">
<button class="menubar-trigger">Edit</button>
</div>
<div class="menubar-menu">
<button class="menubar-trigger">View</button>
</div>
<div class="menubar-menu">
<button class="menubar-trigger">Help</button>
</div>
</nav>
<!-- Glass -->
<nav class="menubar glass">
<div class="menubar-menu">
<button class="menubar-trigger">File</button>
</div>
<div class="menubar-menu">
<button class="menubar-trigger">Edit</button>
</div>
<div class="menubar-menu">
<button class="menubar-trigger">View</button>
</div>
<div class="menubar-menu">
<button class="menubar-trigger">Help</button>
</div>
</nav>
</div> Requires: ux.min.css
<div class="flex flex-col gap-4">
<!-- Compact (32px height, smaller text) -->
<nav class="inline-flex items-center gap-0.5 h-8 p-0.5 bg-base-100 border border-base-300 rounded-box shadow-xs">
<div class="relative"><button class="flex items-center justify-center px-1.5 py-0.5 text-xs font-medium bg-transparent rounded-field border-none cursor-pointer hover:bg-base-200" style="color: var(--color-base-content);">File</button></div>
<div class="relative"><button class="flex items-center justify-center px-1.5 py-0.5 text-xs font-medium bg-transparent rounded-field border-none cursor-pointer hover:bg-base-200" style="color: var(--color-base-content);">Edit</button></div>
<div class="relative"><button class="flex items-center justify-center px-1.5 py-0.5 text-xs font-medium bg-transparent rounded-field border-none cursor-pointer hover:bg-base-200" style="color: var(--color-base-content);">View</button></div>
<div class="relative"><button class="flex items-center justify-center px-1.5 py-0.5 text-xs font-medium bg-transparent rounded-field border-none cursor-pointer hover:bg-base-200" style="color: var(--color-base-content);">Help</button></div>
</nav>
<!-- Glass -->
<nav class="inline-flex items-center gap-0.5 h-9 p-0.5 glass rounded-box shadow-xs">
<div class="relative"><button class="flex items-center justify-center px-2 py-1 text-sm font-medium bg-transparent rounded-field border-none cursor-pointer hover:bg-white/10" style="color: var(--color-base-content);">File</button></div>
<div class="relative"><button class="flex items-center justify-center px-2 py-1 text-sm font-medium bg-transparent rounded-field border-none cursor-pointer hover:bg-white/10" style="color: var(--color-base-content);">Edit</button></div>
<div class="relative"><button class="flex items-center justify-center px-2 py-1 text-sm font-medium bg-transparent rounded-field border-none cursor-pointer hover:bg-white/10" style="color: var(--color-base-content);">View</button></div>
<div class="relative"><button class="flex items-center justify-center px-2 py-1 text-sm font-medium bg-transparent rounded-field border-none cursor-pointer hover:bg-white/10" style="color: var(--color-base-content);">Help</button></div>
</nav>
</div> Requires: tw.min.css
// No JavaScript required Classes Reference
| Class | Description |
|---|---|
| .menubar | Container bar |
| .menubar-menu | Individual menu wrapper |
| .menubar-trigger | Top-level menu trigger button |
| .menubar-content | Dropdown panel |
| .menubar-item | Menu item |
| .menubar-item-destructive | Red destructive item |
| .menubar-item-disabled | Disabled item |
| .menubar-item-inset | Extra left padding (icon space) |
| .menubar-icon | Item icon |
| .menubar-shortcut | Keyboard shortcut text |
| .menubar-separator | Horizontal divider |
| .menubar-label | Section header |
| .menubar-checkbox / .menubar-radio | Check/radio items |
| .menubar-indicator | Check/radio indicator icon |
| .menubar-sub | Submenu wrapper |
| .menubar-sub-trigger | Submenu trigger |
| .menubar-sub-arrow | Submenu chevron icon |
| .menubar-sub-content | Submenu dropdown panel |
| .menubar-compact | Smaller compact variant (32px) |
| .menubar.glass | Frosted glass variant |