HextaUI

Menubar

Eine Menüleiste im Desktop-Stil mit einem Highlight, das zwischen offenen Menüs gleitet, und sofortigem Wechsel, wenn du darüberfährst.

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

export function MenubarDemo() {
  return (
    <Menubar aria-label="Editor">
      <MenubarMenu>
        <MenubarTrigger>File</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>
            New tab
            <MenubarShortcut>
              <KbdGroup keys="mod+t" variant="flat" size="sm" />
            </MenubarShortcut>
          </MenubarItem>
          <MenubarItem>
            New window
            <MenubarShortcut>
              <KbdGroup keys="mod+n" variant="flat" size="sm" />
            </MenubarShortcut>
          </MenubarItem>
          <MenubarItem disabled>New incognito window</MenubarItem>
          <MenubarSeparator />
          <MenubarSub>
            <MenubarSubTrigger>Share</MenubarSubTrigger>
            <MenubarSubContent>
              <MenubarItem>Email link</MenubarItem>
              <MenubarItem>Messages</MenubarItem>
              <MenubarItem>Notes</MenubarItem>
            </MenubarSubContent>
          </MenubarSub>
          <MenubarSeparator />
          <MenubarItem>
            Print…
            <MenubarShortcut>
              <KbdGroup keys="mod+p" variant="flat" size="sm" />
            </MenubarShortcut>
          </MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger>Edit</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>
            Undo
            <MenubarShortcut>
              <KbdGroup keys="mod+z" variant="flat" size="sm" />
            </MenubarShortcut>
          </MenubarItem>
          <MenubarItem>
            Redo
            <MenubarShortcut>
              <KbdGroup keys="mod+shift+z" variant="flat" size="sm" />
            </MenubarShortcut>
          </MenubarItem>
          <MenubarSeparator />
          <MenubarSub>
            <MenubarSubTrigger>Find</MenubarSubTrigger>
            <MenubarSubContent>
              <MenubarItem>Search the web</MenubarItem>
              <MenubarSeparator />
              <MenubarItem>Find…</MenubarItem>
              <MenubarItem>Find next</MenubarItem>
              <MenubarItem>Find previous</MenubarItem>
            </MenubarSubContent>
          </MenubarSub>
          <MenubarSeparator />
          <MenubarItem>Cut</MenubarItem>
          <MenubarItem>Copy</MenubarItem>
          <MenubarItem>Paste</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger>View</MenubarTrigger>
        <MenubarContent>
          <MenubarCheckboxItem>Always show bookmarks bar</MenubarCheckboxItem>
          <MenubarCheckboxItem defaultChecked>
            Always show full URLs
          </MenubarCheckboxItem>
          <MenubarSeparator />
          <MenubarItem inset>
            Reload
            <MenubarShortcut>
              <KbdGroup keys="mod+r" variant="flat" size="sm" />
            </MenubarShortcut>
          </MenubarItem>
          <MenubarItem inset disabled>
            Force reload
            <MenubarShortcut>
              <KbdGroup keys="mod+shift+r" variant="flat" size="sm" />
            </MenubarShortcut>
          </MenubarItem>
          <MenubarSeparator />
          <MenubarItem inset>Toggle full screen</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger>Profiles</MenubarTrigger>
        <MenubarContent>
          <MenubarGroup>
            <MenubarLabel>Switch profile</MenubarLabel>
            <MenubarRadioGroup defaultValue="mira">
              <MenubarRadioItem value="jun">Jun</MenubarRadioItem>
              <MenubarRadioItem value="mira">Mira</MenubarRadioItem>
              <MenubarRadioItem value="sol">Sol</MenubarRadioItem>
            </MenubarRadioGroup>
          </MenubarGroup>
          <MenubarSeparator />
          <MenubarItem inset>Edit…</MenubarItem>
          <MenubarItem inset>Add profile…</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
    </Menubar>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/menubar.json

Fügt die Komponente, die HextaUI-Theme-Tokens und alle HextaUI-Komponenten hinzu, von denen sie abhängt.

import {
  Menubar,
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarShortcut,
  MenubarTrigger,
} from "@/components/ui/menubar"
<Menubar aria-label="Editor">
  <MenubarMenu>
    <MenubarTrigger>File</MenubarTrigger>
    <MenubarContent>
      <MenubarItem>
        New tab <MenubarShortcut>⌘T</MenubarShortcut>
      </MenubarItem>
    </MenubarContent>
  </MenubarMenu>
</Menubar>

Jedes <MenubarMenu /> ist ein Dropdown menu, daher funktionieren Items, Checkbox- und Radio-Items, Untermenüs, Labels und Tastenkürzel und sehen genau gleich aus. Öffne ein Menü und bewege dann den Zeiger oder drücke die Pfeiltasten, um über die Leiste zu streichen.

Menubar
└── MenubarMenu
    ├── MenubarTrigger
    └── MenubarContent
        ├── MenubarGroup
        │   ├── MenubarLabel
        │   └── MenubarItem
        │       └── MenubarShortcut
        ├── MenubarCheckboxItem
        ├── MenubarRadioGroup
        │   └── MenubarRadioItem
        ├── MenubarSeparator
        └── MenubarSub
            ├── MenubarSubTrigger
            └── MenubarSubContent

Trigger-Icons

Setze ein Icon vor das Label eines Triggers oder verwende ein Icon allein mit einem aria-label. Trigger nur mit Icon erhalten eine quadratische Form.

import {
  IconAdjustmentsHorizontal,
  IconDots,
  IconFolder,
  IconLayoutGrid,
  IconPencil,
} from "@tabler/icons-react"

import {
  Menubar,
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarSeparator,
  MenubarTrigger,
} from "@/components/ui/menubar"

export function MenubarTriggerIcons() {
  return (
    <Menubar aria-label="Project">
      <MenubarMenu>
        <MenubarTrigger>
          <IconFolder />
          Project
        </MenubarTrigger>
        <MenubarContent>
          <MenubarItem>Open…</MenubarItem>
          <MenubarItem>Duplicate</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger>
          <IconPencil />
          Edit
        </MenubarTrigger>
        <MenubarContent>
          <MenubarItem>Rename</MenubarItem>
          <MenubarItem>Move</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger>
          <IconLayoutGrid />
          View
        </MenubarTrigger>
        <MenubarContent>
          <MenubarItem>Grid</MenubarItem>
          <MenubarItem>List</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger aria-label="More">
          <IconDots />
        </MenubarTrigger>
        <MenubarContent align="end">
          <MenubarItem>
            <IconAdjustmentsHorizontal />
            Preferences
          </MenubarItem>
          <MenubarSeparator />
          <MenubarItem variant="destructive">Delete project</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
    </Menubar>
  )
}

Icons

Setze ein Icon vor das Label. Verwende variant="destructive" bei Items, die löschen oder nicht rückgängig zu machen sind.

import {
  IconCopy,
  IconDownload,
  IconFilePlus,
  IconFolderOpen,
  IconScissors,
  IconTrash,
} from "@tabler/icons-react"

import {
  Menubar,
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarSeparator,
  MenubarShortcut,
  MenubarTrigger,
} from "@/components/ui/menubar"

export function MenubarIcons() {
  return (
    <Menubar aria-label="Files">
      <MenubarMenu>
        <MenubarTrigger>File</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>
            <IconFilePlus />
            New file
            <MenubarShortcut>⌘N</MenubarShortcut>
          </MenubarItem>
          <MenubarItem>
            <IconFolderOpen />
            Open…
            <MenubarShortcut>⌘O</MenubarShortcut>
          </MenubarItem>
          <MenubarItem>
            <IconDownload />
            Export
          </MenubarItem>
          <MenubarSeparator />
          <MenubarItem variant="destructive">
            <IconTrash />
            Move to trash
          </MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger>Edit</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>
            <IconScissors />
            Cut
            <MenubarShortcut>⌘X</MenubarShortcut>
          </MenubarItem>
          <MenubarItem>
            <IconCopy />
            Copy
            <MenubarShortcut>⌘C</MenubarShortcut>
          </MenubarItem>
        </MenubarContent>
      </MenubarMenu>
    </Menubar>
  )
}

Deaktiviert

Deaktiviere ein einzelnes Menü mit disabled an <MenubarMenu /> oder die ganze Leiste an <Menubar />. Pfeiltasten überspringen deaktivierte Menüs.

import {
  Menubar,
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarTrigger,
} from "@/components/ui/menubar"

export function MenubarDisabled() {
  return (
    <div className="flex flex-col items-center gap-4">
      <Menubar aria-label="Document">
        <MenubarMenu>
          <MenubarTrigger>File</MenubarTrigger>
          <MenubarContent>
            <MenubarItem>Save</MenubarItem>
          </MenubarContent>
        </MenubarMenu>
        <MenubarMenu disabled>
          <MenubarTrigger>Review</MenubarTrigger>
          <MenubarContent>
            <MenubarItem>Accept all changes</MenubarItem>
          </MenubarContent>
        </MenubarMenu>
        <MenubarMenu>
          <MenubarTrigger>Help</MenubarTrigger>
          <MenubarContent>
            <MenubarItem>Keyboard shortcuts</MenubarItem>
          </MenubarContent>
        </MenubarMenu>
      </Menubar>
      <Menubar aria-label="Locked document" disabled>
        <MenubarMenu>
          <MenubarTrigger>File</MenubarTrigger>
          <MenubarContent>
            <MenubarItem>Save</MenubarItem>
          </MenubarContent>
        </MenubarMenu>
        <MenubarMenu>
          <MenubarTrigger>Edit</MenubarTrigger>
          <MenubarContent>
            <MenubarItem>Undo</MenubarItem>
          </MenubarContent>
        </MenubarMenu>
      </Menubar>
    </div>
  )
}

Vertikal

orientation="vertical" stapelt die Menüs und schaltet die Navigation auf die Pfeiltasten nach oben und unten um. Öffne die Menüs zur Seite mit side="inline-end".

import {
  Menubar,
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarTrigger,
} from "@/components/ui/menubar"

const menus = [
  { label: "Projects", items: ["All projects", "Starred", "Archived"] },
  { label: "Team", items: ["Members", "Roles", "Invitations"] },
  { label: "Billing", items: ["Plan", "Invoices", "Payment method"] },
]

export function MenubarVertical() {
  return (
    <Menubar aria-label="Workspace" orientation="vertical">
      {menus.map((menu) => (
        <MenubarMenu key={menu.label}>
          <MenubarTrigger>{menu.label}</MenubarTrigger>
          <MenubarContent side="inline-end" align="start" sideOffset={8}>
            {menu.items.map((item) => (
              <MenubarItem key={item}>{item}</MenubarItem>
            ))}
          </MenubarContent>
        </MenubarMenu>
      ))}
    </Menubar>
  )
}

Rechts nach links

Menüs, Untermenüs und Pfeiltasten folgen der Leserichtung. Tastenkürzel behalten die Tastaturreihenfolge.

import {
  Menubar,
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarShortcut,
  MenubarSub,
  MenubarSubContent,
  MenubarSubTrigger,
  MenubarTrigger,
} from "@/components/ui/menubar"

export function MenubarRtl() {
  return (
    <div dir="rtl">
      <Menubar aria-label="المحرر">
        <MenubarMenu>
          <MenubarTrigger>ملف</MenubarTrigger>
          <MenubarContent>
            <MenubarItem>
              علامة تبويب جديدة
              <MenubarShortcut>⌘T</MenubarShortcut>
            </MenubarItem>
            <MenubarSub>
              <MenubarSubTrigger>مشاركة</MenubarSubTrigger>
              <MenubarSubContent>
                <MenubarItem>رابط البريد</MenubarItem>
              </MenubarSubContent>
            </MenubarSub>
          </MenubarContent>
        </MenubarMenu>
        <MenubarMenu>
          <MenubarTrigger>تحرير</MenubarTrigger>
          <MenubarContent>
            <MenubarItem>تراجع</MenubarItem>
            <MenubarItem>إعادة</MenubarItem>
          </MenubarContent>
        </MenubarMenu>
      </Menubar>
    </div>
  )
}
TasteAktion
TabSetzt den Fokus in die Menubar und wieder hinaus.
←→Wechselt zwischen Menüs. Bei offenem Menü wird stattdessen das nächste geöffnet.
EnterSpace↓Öffnet das fokussierte Menü.
↑↓Wechselt zwischen Items in einem offenen Menü.
→Öffnet ein Untermenü von seinem Trigger aus.
EscSchließt das offene Menü und gibt den Fokus an seinen Trigger zurück.
  • Gib der Menubar mit aria-label einen Namen. Sie rendert role="menubar", und jeder Trigger ist ein Menüeintrag, sodass Screenreader sie als Anwendungsmenü ansagen.
  • Die Leiste ist ein einziger Tab-Stopp. Pfeiltasten wechseln zwischen Menüs, sodass die Tab-Reihenfolge der Seite kurz bleibt.
  • Das gleitende Highlight ist Dekoration. Bei reduzierter Bewegung erscheint es einfach am offenen Menü.

Menüteile akzeptieren dieselben Props wie ihre Gegenstücke im Dropdown menu.

PropTypStandard
orientation
"horizontal" | "vertical""horizontal"
loopFocusVom letzten Menü zurück zum ersten springen.
booleantrue
modalBlockiere das Scrollen der Seite und Klicks außerhalb, solange ein Menü offen ist.
booleantrue
disabled
booleanfalse
render
ReactElement | (props, state) => ReactElement<div>
AttributBeschreibung
data-slot="menubar"Die Leiste per CSS ansprechen.
data-orientationDie Ausrichtung.
data-has-submenu-openVorhanden, solange ein beliebiges Menü der Leiste offen ist.
data-slot="menubar-highlight"Der gleitende Hintergrund hinter dem offenen Trigger, mit data-visible.
--menubar-radiusEckenradius der Leiste. Trigger und Highlight leiten ihren davon ab.
PropTypStandard
open
boolean–
defaultOpen
booleanfalse
onOpenChange
(open: boolean, details) => void–
disabled
booleanfalse
AttributBeschreibung
data-slot="menubar-trigger"Trigger in CSS ansprechen.
data-popup-openVorhanden, solange das Menü geöffnet ist.
data-disabledVorhanden, wenn deaktiviert.
PropTypStandard
side
"top" | "bottom" | "left" | "right" | "inline-start" | "inline-end""bottom"
align
"start" | "center" | "end""start"
sideOffset
number8
alignOffsetRichtet die Items des Menüs am Label des Triggers aus.
number-4
AttributBeschreibung
data-slot="menubar-content"Menüs per CSS ansprechen.
data-instant="group"Vorhanden, wenn das Menü durch Überstreichen von einem anderen aus geöffnet wurde. Es wechselt ohne Animation.

MenubarItem, MenubarCheckboxItem, MenubarRadioGroup, MenubarRadioItem, MenubarGroup, MenubarLabel, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubTrigger und MenubarSubContent sind die Teile des Dropdown menu mit menubar-*-Slots. Ihre Props findest du in der API des Dropdown menu.