Components

Menubar

A persistent menu, common in desktop apps, with quick access to a set of commands.

Installation

Cortexcn
pnpm dlx shadcn@latest add @cortexcn/menubar

Usage

import { Menubar, MenubarPortal, MenubarMenu, MenubarTrigger, MenubarContent, MenubarGroup, MenubarSeparator, MenubarLabel, MenubarItem, MenubarShortcut, MenubarCheckboxItem, MenubarRadioGroup, MenubarRadioItem, MenubarSub, MenubarSubTrigger, MenubarSubContent } from "@/components/menubar";

Examples

Basic

import { Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarTrigger } from "@/components/menubar"export function MenubarBasic() {  return (    <div className="flex flex-col gap-6">      <Menubar>        <MenubarMenu>          <MenubarTrigger>File</MenubarTrigger>          <MenubarContent>            <MenubarGroup>              <MenubarItem>                New Tab <MenubarShortcut>⌘T</MenubarShortcut>              </MenubarItem>              <MenubarItem>                New Window <MenubarShortcut>⌘N</MenubarShortcut>              </MenubarItem>              <MenubarItem disabled>New Incognito Window</MenubarItem>            </MenubarGroup>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem>                Print... <MenubarShortcut>⌘P</MenubarShortcut>              </MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>        <MenubarMenu>          <MenubarTrigger>Edit</MenubarTrigger>          <MenubarContent>            <MenubarGroup>              <MenubarItem>                Undo <MenubarShortcut>⌘Z</MenubarShortcut>              </MenubarItem>              <MenubarItem>                Redo <MenubarShortcut>⇧⌘Z</MenubarShortcut>              </MenubarItem>            </MenubarGroup>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem>Cut</MenubarItem>              <MenubarItem>Copy</MenubarItem>              <MenubarItem>Paste</MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>      </Menubar>    </div>  )}

With submenu

import { Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from "@/components/menubar"export function MenubarWithSubmenu() {  return (    <div className="flex flex-col gap-6">      <Menubar>        <MenubarMenu>          <MenubarTrigger>File</MenubarTrigger>          <MenubarContent>            <MenubarSub>              <MenubarSubTrigger>Share</MenubarSubTrigger>              <MenubarSubContent>                <MenubarGroup>                  <MenubarItem>Email link</MenubarItem>                  <MenubarItem>Messages</MenubarItem>                  <MenubarItem>Notes</MenubarItem>                </MenubarGroup>              </MenubarSubContent>            </MenubarSub>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem>                Print... <MenubarShortcut>⌘P</MenubarShortcut>              </MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>        <MenubarMenu>          <MenubarTrigger>Edit</MenubarTrigger>          <MenubarContent>            <MenubarGroup>              <MenubarItem>                Undo <MenubarShortcut>⌘Z</MenubarShortcut>              </MenubarItem>              <MenubarItem>                Redo <MenubarShortcut>⇧⌘Z</MenubarShortcut>              </MenubarItem>            </MenubarGroup>            <MenubarSeparator />            <MenubarSub>              <MenubarSubTrigger>Find</MenubarSubTrigger>              <MenubarSubContent>                <MenubarGroup>                  <MenubarItem>Find...</MenubarItem>                  <MenubarItem>Find Next</MenubarItem>                  <MenubarItem>Find Previous</MenubarItem>                </MenubarGroup>              </MenubarSubContent>            </MenubarSub>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem>Cut</MenubarItem>              <MenubarItem>Copy</MenubarItem>              <MenubarItem>Paste</MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>      </Menubar>    </div>  )}

With checkboxes

import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarTrigger } from "@/components/menubar"export function MenubarWithCheckboxes() {  return (    <div className="flex flex-col gap-6">      <Menubar>        <MenubarMenu>          <MenubarTrigger>View</MenubarTrigger>          <MenubarContent className="w-64">            <MenubarGroup>              <MenubarCheckboxItem>                Always Show Bookmarks Bar              </MenubarCheckboxItem>              <MenubarCheckboxItem checked>                Always Show Full URLs              </MenubarCheckboxItem>            </MenubarGroup>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem inset>                Reload <MenubarShortcut>⌘R</MenubarShortcut>              </MenubarItem>              <MenubarItem disabled inset>                Force Reload <MenubarShortcut>⇧⌘R</MenubarShortcut>              </MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>        <MenubarMenu>          <MenubarTrigger>Format</MenubarTrigger>          <MenubarContent>            <MenubarCheckboxItem checked>Strikethrough</MenubarCheckboxItem>            <MenubarCheckboxItem>Code</MenubarCheckboxItem>            <MenubarCheckboxItem>Superscript</MenubarCheckboxItem>          </MenubarContent>        </MenubarMenu>      </Menubar>    </div>  )}

With radio

import * as React from "react"import { Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarTrigger } from "@/components/menubar"export function MenubarWithRadio() {  const [user, setUser] = React.useState("benoit")  const [theme, setTheme] = React.useState("system")  return (    <div className="flex flex-col gap-6">      <Menubar>        <MenubarMenu>          <MenubarTrigger>Profiles</MenubarTrigger>          <MenubarContent>            <MenubarRadioGroup value={user} onValueChange={setUser}>              <MenubarRadioItem value="andy">Andy</MenubarRadioItem>              <MenubarRadioItem value="benoit">Benoit</MenubarRadioItem>              <MenubarRadioItem value="luis">Luis</MenubarRadioItem>            </MenubarRadioGroup>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem inset>Edit...</MenubarItem>              <MenubarItem inset>Add Profile...</MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>        <MenubarMenu>          <MenubarTrigger>Theme</MenubarTrigger>          <MenubarContent>            <MenubarRadioGroup value={theme} onValueChange={setTheme}>              <MenubarRadioItem value="light">Light</MenubarRadioItem>              <MenubarRadioItem value="dark">Dark</MenubarRadioItem>              <MenubarRadioItem value="system">System</MenubarRadioItem>            </MenubarRadioGroup>          </MenubarContent>        </MenubarMenu>      </Menubar>    </div>  )}

With icons

import { Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarTrigger } from "@/components/menubar"import { CircleDashedIcon, FileIcon, FolderIcon, SaveIcon } from "lucide-react"export function MenubarWithIcons() {  return (    <div className="flex flex-col gap-6">      <Menubar>        <MenubarMenu>          <MenubarTrigger>File</MenubarTrigger>          <MenubarContent>            <MenubarGroup>              <MenubarItem>                <FileIcon />                New File <MenubarShortcut>⌘N</MenubarShortcut>              </MenubarItem>              <MenubarItem>                <FolderIcon />                Open Folder              </MenubarItem>            </MenubarGroup>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem>                <SaveIcon />                Save <MenubarShortcut>⌘S</MenubarShortcut>              </MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>        <MenubarMenu>          <MenubarTrigger>More</MenubarTrigger>          <MenubarContent>            <MenubarGroup>              <MenubarItem>                <CircleDashedIcon />                Settings              </MenubarItem>              <MenubarItem>                <CircleDashedIcon />                Help              </MenubarItem>              <MenubarSeparator />              <MenubarItem variant="destructive">                <CircleDashedIcon />                Delete              </MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>      </Menubar>    </div>  )}

With shortcuts

import { Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarTrigger } from "@/components/menubar"export function MenubarWithShortcuts() {  return (    <div className="flex flex-col gap-6">      <Menubar>        <MenubarMenu>          <MenubarTrigger>File</MenubarTrigger>          <MenubarContent>            <MenubarGroup>              <MenubarItem>                New Tab <MenubarShortcut>⌘T</MenubarShortcut>              </MenubarItem>              <MenubarItem>                New Window <MenubarShortcut>⌘N</MenubarShortcut>              </MenubarItem>              <MenubarItem>                Print... <MenubarShortcut>⌘P</MenubarShortcut>              </MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>        <MenubarMenu>          <MenubarTrigger>Edit</MenubarTrigger>          <MenubarContent>            <MenubarGroup>              <MenubarItem>                Undo <MenubarShortcut>⌘Z</MenubarShortcut>              </MenubarItem>              <MenubarItem>                Redo <MenubarShortcut>⇧⌘Z</MenubarShortcut>              </MenubarItem>            </MenubarGroup>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem>                Cut <MenubarShortcut>⌘X</MenubarShortcut>              </MenubarItem>              <MenubarItem>                Copy <MenubarShortcut>⌘C</MenubarShortcut>              </MenubarItem>              <MenubarItem>                Paste <MenubarShortcut>⌘V</MenubarShortcut>              </MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>      </Menubar>    </div>  )}

Format

import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarTrigger } from "@/components/menubar"import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"export function MenubarFormat() {  return (    <div className="flex flex-col gap-6">      <Menubar>        <MenubarMenu>          <MenubarTrigger>Format</MenubarTrigger>          <MenubarContent>            <MenubarGroup>              <MenubarItem>                <BoldIcon />                Bold <MenubarShortcut>⌘B</MenubarShortcut>              </MenubarItem>              <MenubarItem>                <ItalicIcon />                Italic <MenubarShortcut>⌘I</MenubarShortcut>              </MenubarItem>              <MenubarItem>                <UnderlineIcon />                Underline <MenubarShortcut>⌘U</MenubarShortcut>              </MenubarItem>            </MenubarGroup>            <MenubarSeparator />            <MenubarGroup>              <MenubarCheckboxItem checked>Strikethrough</MenubarCheckboxItem>              <MenubarCheckboxItem>Code</MenubarCheckboxItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>        <MenubarMenu>          <MenubarTrigger>View</MenubarTrigger>          <MenubarContent>            <MenubarCheckboxItem>Show Ruler</MenubarCheckboxItem>            <MenubarCheckboxItem checked>Show Grid</MenubarCheckboxItem>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem inset>Zoom In</MenubarItem>              <MenubarItem inset>Zoom Out</MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>      </Menubar>    </div>  )}

Insert

import { Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from "@/components/menubar"import { CheckIcon, ImageIcon, LinkIcon, SearchIcon, TableIcon } from "lucide-react"export function MenubarInsert() {  return (    <div className="flex flex-col gap-6">      <Menubar>        <MenubarMenu>          <MenubarTrigger>Insert</MenubarTrigger>          <MenubarContent>            <MenubarSub>              <MenubarSubTrigger>                <ImageIcon />                Media              </MenubarSubTrigger>              <MenubarSubContent>                <MenubarGroup>                  <MenubarItem>Image</MenubarItem>                  <MenubarItem>Video</MenubarItem>                  <MenubarItem>Audio</MenubarItem>                </MenubarGroup>              </MenubarSubContent>            </MenubarSub>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem>                <LinkIcon />                Link <MenubarShortcut>⌘K</MenubarShortcut>              </MenubarItem>              <MenubarItem>                <TableIcon />                Table              </MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>        <MenubarMenu>          <MenubarTrigger>Tools</MenubarTrigger>          <MenubarContent className="w-44">            <MenubarGroup>              <MenubarItem>                <SearchIcon />                Find & Replace <MenubarShortcut>⌘F</MenubarShortcut>              </MenubarItem>              <MenubarItem>                <CheckIcon />                Spell Check              </MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>      </Menubar>    </div>  )}

Destructive

import { Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarTrigger } from "@/components/menubar"import { FileIcon, FolderIcon, LogOutIcon, SettingsIcon, TrashIcon, UserIcon } from "lucide-react"export function MenubarDestructive() {  return (    <div className="flex flex-col gap-6">      <Menubar>        <MenubarMenu>          <MenubarTrigger>File</MenubarTrigger>          <MenubarContent className="w-40">            <MenubarGroup>              <MenubarItem>                <FileIcon />                New File <MenubarShortcut>⌘N</MenubarShortcut>              </MenubarItem>              <MenubarItem>                <FolderIcon />                Open Folder              </MenubarItem>            </MenubarGroup>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem variant="destructive">                <TrashIcon />                Delete File <MenubarShortcut>⌘⌫</MenubarShortcut>              </MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>        <MenubarMenu>          <MenubarTrigger>Account</MenubarTrigger>          <MenubarContent>            <MenubarGroup>              <MenubarItem>                <UserIcon />                Profile              </MenubarItem>              <MenubarItem>                <SettingsIcon />                Settings              </MenubarItem>            </MenubarGroup>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem variant="destructive">                <LogOutIcon />                Sign out              </MenubarItem>            </MenubarGroup>            <MenubarSeparator />            <MenubarGroup>              <MenubarItem variant="destructive">                <TrashIcon />                Delete              </MenubarItem>            </MenubarGroup>          </MenubarContent>        </MenubarMenu>      </Menubar>    </div>  )}

In dialog

import { Button } from "@/components/button"import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/dialog"import { Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from "@/components/menubar"import { ClipboardPasteIcon, CopyIcon, ScissorsIcon, TrashIcon } from "lucide-react"export function MenubarInDialog() {  return (    <div className="flex flex-col gap-6">      <Dialog>        <DialogTrigger asChild>          <Button variant="outline">Open Dialog</Button>        </DialogTrigger>        <DialogContent>          <DialogHeader>            <DialogTitle>Menubar Example</DialogTitle>            <DialogDescription>              Use the menubar below to see the menu options.            </DialogDescription>          </DialogHeader>          <Menubar>            <MenubarMenu>              <MenubarTrigger>File</MenubarTrigger>              <MenubarContent>                <MenubarGroup>                  <MenubarItem>                    <CopyIcon />                    Copy                  </MenubarItem>                  <MenubarItem>                    <ScissorsIcon />                    Cut                  </MenubarItem>                  <MenubarItem>                    <ClipboardPasteIcon />                    Paste                  </MenubarItem>                </MenubarGroup>                <MenubarSeparator />                <MenubarSub>                  <MenubarSubTrigger>More Options</MenubarSubTrigger>                  <MenubarSubContent>                    <MenubarGroup>                      <MenubarItem>Save Page...</MenubarItem>                      <MenubarItem>Create Shortcut...</MenubarItem>                      <MenubarItem>Name Window...</MenubarItem>                    </MenubarGroup>                    <MenubarSeparator />                    <MenubarGroup>                      <MenubarItem>Developer Tools</MenubarItem>                    </MenubarGroup>                  </MenubarSubContent>                </MenubarSub>                <MenubarSeparator />                <MenubarGroup>                  <MenubarItem variant="destructive">                    <TrashIcon />                    Delete                  </MenubarItem>                </MenubarGroup>              </MenubarContent>            </MenubarMenu>            <MenubarMenu>              <MenubarTrigger>Edit</MenubarTrigger>              <MenubarContent>                <MenubarGroup>                  <MenubarItem>                    Undo <MenubarShortcut>⌘Z</MenubarShortcut>                  </MenubarItem>                  <MenubarItem>                    Redo <MenubarShortcut>⇧⌘Z</MenubarShortcut>                  </MenubarItem>                </MenubarGroup>              </MenubarContent>            </MenubarMenu>          </Menubar>        </DialogContent>      </Dialog>    </div>  )}

With inset

import * as React from "react"import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from "@/components/menubar"import { CopyIcon, ScissorsIcon } from "lucide-react"export function MenubarWithInset() {  const [showBookmarks, setShowBookmarks] = React.useState(true)  const [showUrls, setShowUrls] = React.useState(false)  const [theme, setTheme] = React.useState("system")  return (    <div className="flex flex-col gap-6">      <Menubar>        <MenubarMenu>          <MenubarTrigger>View</MenubarTrigger>          <MenubarContent className="w-44">            <MenubarGroup>              <MenubarLabel>Actions</MenubarLabel>              <MenubarItem>                <CopyIcon />                Copy              </MenubarItem>              <MenubarItem>                <ScissorsIcon />                Cut              </MenubarItem>              <MenubarItem inset>Paste</MenubarItem>            </MenubarGroup>            <MenubarSeparator />            <MenubarGroup>              <MenubarLabel inset>Appearance</MenubarLabel>              <MenubarCheckboxItem                inset                checked={showBookmarks}                onCheckedChange={setShowBookmarks}              >                Bookmarks              </MenubarCheckboxItem>              <MenubarCheckboxItem                inset                checked={showUrls}                onCheckedChange={setShowUrls}              >                Full URLs              </MenubarCheckboxItem>            </MenubarGroup>            <MenubarSeparator />            <MenubarGroup>              <MenubarLabel inset>Theme</MenubarLabel>              <MenubarRadioGroup value={theme} onValueChange={setTheme}>                <MenubarRadioItem inset value="light">                  Light                </MenubarRadioItem>                <MenubarRadioItem inset value="dark">                  Dark                </MenubarRadioItem>                <MenubarRadioItem inset value="system">                  System                </MenubarRadioItem>              </MenubarRadioGroup>            </MenubarGroup>            <MenubarSeparator />            <MenubarSub>              <MenubarSubTrigger inset>More Options</MenubarSubTrigger>              <MenubarSubContent>                <MenubarGroup>                  <MenubarItem>Save Page...</MenubarItem>                  <MenubarItem>Create Shortcut...</MenubarItem>                </MenubarGroup>              </MenubarSubContent>            </MenubarSub>          </MenubarContent>        </MenubarMenu>      </Menubar>    </div>  )}

Adapted from the shadcn/ui Menubar (MIT).