Menubar

A row of menus, the way a desktop application has one.

Installation

uvx django_shadcn@latest add menubar

Usage

<c-menubar>
    <c-menubar.menu>
        <c-menubar.trigger>File</c-menubar.trigger>
        <c-menubar.content>
            <c-menubar.item>New tab</c-menubar.item>
            <c-menubar.item>Open</c-menubar.item>
        </c-menubar.content>
    </c-menubar.menu>
    <c-menubar.menu>
        <c-menubar.trigger>Help</c-menubar.trigger>
        <c-menubar.content>
            <c-menubar.item>Documentation</c-menubar.item>
        </c-menubar.content>
    </c-menubar.menu>
</c-menubar>

Open one menu and the others answer to hover — moving along the bar switches between them without another click, which is what makes a menubar feel like one. Clicking the open trigger again, picking an item, pressing Escape or clicking away all close it.

Examples

Checkboxes and radios

<c-menubar.checkbox-item checked="true">Status bar</c-menubar.checkbox-item>

<c-menubar.radio-group value="left">
    <c-menubar.radio-item value="left">Left</c-menubar.radio-item>
    <c-menubar.radio-item value="right">Right</c-menubar.radio-item>
</c-menubar.radio-group>

Submenu

<c-menubar.sub>
    <c-menubar.sub-trigger>Share</c-menubar.sub-trigger>
    <c-menubar.sub-content class="w-40">
        <c-menubar.item>Copy link</c-menubar.item>
        <c-menubar.item>Email</c-menubar.item>
    </c-menubar.sub-content>
</c-menubar.sub>

Alignment

<c-menubar.content align="start">...</c-menubar.content>
<c-menubar.content align="end">...</c-menubar.content>

Notes

Which menu is open is tracked by element identity rather than a name you have to invent, so a <c-menubar.menu> needs no value. The trigger and the content find each other through the menu they share as a parent, which is why both have to be direct children of it.

Like the context menu, there is no roving focus: the bar answers to the pointer and to Escape, not to the arrow keys. The content is positioned against its trigger with utility classes, so align is a choice rather than a measurement — a menu near the right edge wants align="end".