Skip to main content
Gremorie
Navigation

Menubar

Barra de múltiplos menus horizontal no estilo de app desktop. File, Edit, View, Help com submenus, checkboxes, radios e atalhos.

Visão geral

Menubar é o primitivo de barra de menus de app desktop: vários menus dispostos lado a lado (File, Edit, View, Help), cada um abrindo um dropdown de itens, checkboxes, radios e submenus aninhados. Construído sobre o Radix Menubar, ele implementa o contrato de teclado entre menus que os usuários esperam de menus nativos - uma vez que um menu está aberto, as setas caminham para o próximo sem reapertar o trigger.

Use o Menubar quando você está emulando uma aplicação desktop - editores de código, planilhas, editores de imagem, IDEs. Para todo o resto - nav de site, menus de ação de botão único, painéis de configuração - use NavigationMenu ou DropdownMenu.

Preview

'use client';import {  Menubar,  MenubarCheckboxItem,  MenubarContent,  MenubarItem,  MenubarMenu,  MenubarRadioGroup,  MenubarRadioItem,  MenubarSeparator,  MenubarShortcut,  MenubarTrigger,} from '@gremorie/rx-navigation';export function MenubarPreview() {  return (    <Menubar>      <MenubarMenu>        <MenubarTrigger>File</MenubarTrigger>        <MenubarContent>          <MenubarItem>            New tab <MenubarShortcut>CtrlT</MenubarShortcut>          </MenubarItem>          <MenubarItem>            New window <MenubarShortcut>CtrlN</MenubarShortcut>          </MenubarItem>          <MenubarSeparator />          <MenubarItem>Print...</MenubarItem>        </MenubarContent>      </MenubarMenu>      <MenubarMenu>        <MenubarTrigger>View</MenubarTrigger>        <MenubarContent>          <MenubarCheckboxItem checked>            Always show bookmarks          </MenubarCheckboxItem>          <MenubarCheckboxItem>Show full URL</MenubarCheckboxItem>          <MenubarSeparator />          <MenubarRadioGroup value="comfortable">            <MenubarRadioItem value="compact">Compact</MenubarRadioItem>            <MenubarRadioItem value="comfortable">Comfortable</MenubarRadioItem>          </MenubarRadioGroup>        </MenubarContent>      </MenubarMenu>    </Menubar>  );}

Anatomia

Menubar
└─ MenubarMenu                      one top-level menu (File, Edit, …)
   ├─ MenubarTrigger                clickable label that opens the menu
   └─ MenubarContent                portaled dropdown panel
      ├─ MenubarItem                command row (inset / destructive variants)
      │  └─ MenubarShortcut         right-aligned keyboard hint
      ├─ MenubarCheckboxItem        toggleable item with a check indicator
      ├─ MenubarRadioGroup          single-choice group
      │  └─ MenubarRadioItem        one radio option with a dot indicator
      ├─ MenubarLabel               non-interactive group header
      ├─ MenubarSeparator           1px divider between groups
      └─ MenubarSub                 nested submenu
         ├─ MenubarSubTrigger       row that opens the submenu
         └─ MenubarSubContent       the submenu panel

Instalação

bash npx gremorie@latest add rx-menubar
bash pnpm dlx gremorie@latest add rx-menubar
bash yarn dlx gremorie@latest add rx-menubar
bash bunx --bun gremorie@latest add rx-menubar

Uso

import {
  Menubar,
  MenubarContent,
  MenubarItem,
  MenubarMenu,
  MenubarSeparator,
  MenubarShortcut,
  MenubarTrigger,
} from "@gremorie/rx-navigation";

export function AppMenubar() {
  return (
    <Menubar>
      <MenubarMenu>
        <MenubarTrigger>File</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>
            New file <MenubarShortcut>CtrlN</MenubarShortcut>
          </MenubarItem>
          <MenubarItem>Open...</MenubarItem>
          <MenubarSeparator />
          <MenubarItem>
            Save <MenubarShortcut>CtrlS</MenubarShortcut>
          </MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger>Edit</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>Undo</MenubarItem>
          <MenubarItem>Redo</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
    </Menubar>
  );
}

A edição Angular deste componente hoje é distribuída a partir do source (veja o side-by-side no workbench); sua entrada no registry vem a seguir.

API

Container raiz. Envolve o Menubar.Root do Radix. Renderiza uma barra horizontal flex h-9 items-center gap-1 rounded-md border bg-background p-1 shadow-xs.

PropTypeDefaultDescription
defaultValuestring-Menu inicialmente aberto, não controlado.
valuestring-Menu aberto controlado.
onValueChange(value: string) => void-Dispara quando o menu aberto muda.
dir"ltr" | "rtl""ltr"Direção de leitura.
loopbooleantrueSe o foco do teclado dá a volta nas pontas da barra.

Um único menu (trigger mais content). Envolve o Menubar.Menu do Radix.

PropTypeDefaultDescription
valuestring-Identificador usado pelo value controlado do Root.

O botão da barra que abre o menu. Envolve o Menubar.Trigger do Radix.

PropTypeDefaultDescription
disabledbooleanfalseDesabilita este trigger.

O painel de dropdown. Envolve o Menubar.Content do Radix dentro de um MenubarPortal.

PropTypeDefaultDescription
align"start" | "center" | "end""start"Alinhamento horizontal relativo ao trigger.
alignOffsetnumber-4Offset em pixels da borda de alinhamento.
sideOffsetnumber8Distância em pixels entre o trigger e o content.
side"top" | "right" | "bottom" | "left""bottom"Lado preferido.
loopbooleantrueSe o foco do teclado dá a volta nas pontas do painel.

Um item de ação padrão.

PropTypeDefaultDescription
insetbooleanfalseQuando true, adiciona padding à esquerda para o item alinhar com itens checkbox / radio.
variant"default" | "destructive""default""destructive" pinta o item e seu ícone no token destructive.
disabledbooleanfalseDesabilita este item.
onSelect(event: Event) => void-Dispara na ativação. Chame event.preventDefault() para manter o menu aberto.

Um item de toggle renderizado com um indicador de check à frente.

PropTypeDefaultDescription
checkedboolean | "indeterminate"falseEstado atual.
onCheckedChange(checked: boolean) => void-Dispara quando o estado muda.
disabledbooleanfalseDesabilita este item.

Um conjunto de radios renderizado com um indicador de ponto à frente.

ComponentPropTypeDescription
RadioGroupvaluestringValor selecionado controlado.
RadioGrouponValueChange(value: string) => voidDispara quando o valor selecionado muda.
RadioItemvaluestringObrigatório. Corresponde ao value do grupo.
RadioItemdisabledbooleanDesabilita este item.

Um header não interativo dentro de um painel de content.

PropTypeDefaultDescription
insetbooleanfalseQuando true, adiciona padding à esquerda para alinhar com itens checkbox / radio.

Um divisor horizontal de 1 px com -mx-1 my-1 para estender por todo o padding do painel.

Um <span> alinhado à direita para a dica de atalho de teclado. Estilizado com ml-auto text-xs tracking-widest text-muted-foreground.

PropTypeDefaultDescription
...propsReact.ComponentProps<"span">-Atributos padrão de span.

Submenus aninhados. O sub-trigger acrescenta automaticamente um chevron apontando para a direita.

ComponentPropTypeDescription
SubdefaultOpenbooleanEstado inicial de aberto, não controlado.
SubopenbooleanEstado de aberto controlado.
SubonOpenChange(open: boolean) => voidDispara quando o sub abre ou fecha.
SubTriggerinsetbooleanAdiciona padding à esquerda para alinhar com itens checkbox / radio.
SubTriggerdisabledbooleanDesabilita o sub-trigger.

MenubarGroup é um wrapper de agrupamento lógico (sem estilo); MenubarPortal é o portal que o Radix usa para montar content (já usado internamente por <MenubarContent>).

Composição

  1. <Menubar> é a barra horizontal.
  2. Cada menu é um <MenubarMenu> contendo um <MenubarTrigger> e um <MenubarContent>.
  3. Dentro do content: uma mistura de <MenubarItem>, <MenubarCheckboxItem>, <MenubarRadioGroup> (com filhos <MenubarRadioItem>), <MenubarLabel>, <MenubarSeparator> e <MenubarSub> para menus aninhados.
  4. Cada item de ação pode carregar um <MenubarShortcut> ao final para a dica de teclado.

O contrato de teclado entre menus é o que distingue o Menubar de uma fileira de DropdownMenus independentes: uma vez que um menu está aberto, ArrowLeft / ArrowRight caminham direto para o content do menu anterior / próximo, sem fechar e reabrir manualmente.

Variações

File / Edit / View com atalhos

'use client';import {  Menubar,  MenubarContent,  MenubarItem,  MenubarMenu,  MenubarSeparator,  MenubarShortcut,  MenubarTrigger,} from '@gremorie/rx-navigation';export function MenubarShortcutsPreview() {  return (    <Menubar>      <MenubarMenu>        <MenubarTrigger>File</MenubarTrigger>        <MenubarContent>          <MenubarItem>            New tab <MenubarShortcut>CtrlT</MenubarShortcut>          </MenubarItem>          <MenubarItem>            New window <MenubarShortcut>CtrlN</MenubarShortcut>          </MenubarItem>          <MenubarSeparator />          <MenubarItem>Print...</MenubarItem>        </MenubarContent>      </MenubarMenu>      <MenubarMenu>        <MenubarTrigger>Edit</MenubarTrigger>        <MenubarContent>          <MenubarItem>            Undo <MenubarShortcut>CtrlZ</MenubarShortcut>          </MenubarItem>          <MenubarItem>            Redo <MenubarShortcut>CtrlShiftZ</MenubarShortcut>          </MenubarItem>        </MenubarContent>      </MenubarMenu>      <MenubarMenu>        <MenubarTrigger>View</MenubarTrigger>        <MenubarContent>          <MenubarItem>Reload</MenubarItem>          <MenubarItem>Fullscreen</MenubarItem>        </MenubarContent>      </MenubarMenu>    </Menubar>  );}

Use como a barra do topo da janela em apps no estilo de editor. Cada menu agrupa comandos relacionados, e <MenubarShortcut> renderiza a dica de teclado alinhada à direita. O texto do atalho é só visual - conecte os bindings reais no seu próprio handler.

Com itens checkbox e radio

<Menubar>
  <MenubarMenu>
    <MenubarTrigger>View</MenubarTrigger>
    <MenubarContent>
      <MenubarCheckboxItem checked>Always show bookmarks</MenubarCheckboxItem>
      <MenubarCheckboxItem>Show full URL</MenubarCheckboxItem>
      <MenubarSeparator />
      <MenubarLabel inset>Density</MenubarLabel>
      <MenubarRadioGroup value="comfortable">
        <MenubarRadioItem value="compact">Compact</MenubarRadioItem>
        <MenubarRadioItem value="comfortable">Comfortable</MenubarRadioItem>
        <MenubarRadioItem value="spacious">Spacious</MenubarRadioItem>
      </MenubarRadioGroup>
    </MenubarContent>
  </MenubarMenu>
</Menubar>

Use para expor preferências de view persistentes. Itens checkbox alternam de forma independente; itens radio escolhem um de N.

'use client';import {  Menubar,  MenubarContent,  MenubarItem,  MenubarMenu,  MenubarSeparator,  MenubarSub,  MenubarSubContent,  MenubarSubTrigger,  MenubarTrigger,} from '@gremorie/rx-navigation';export function MenubarSubmenuPreview() {  return (    <Menubar>      <MenubarMenu>        <MenubarTrigger>File</MenubarTrigger>        <MenubarContent>          <MenubarItem>New file</MenubarItem>          <MenubarSub>            <MenubarSubTrigger>Open recent</MenubarSubTrigger>            <MenubarSubContent>              <MenubarItem>Project alpha</MenubarItem>              <MenubarItem>Project beta</MenubarItem>              <MenubarItem>Project gamma</MenubarItem>            </MenubarSubContent>          </MenubarSub>          <MenubarSeparator />          <MenubarItem variant="destructive">Close window</MenubarItem>        </MenubarContent>      </MenubarMenu>    </Menubar>  );}

Use com moderação. Submenus são valiosos para agrupamento (Open recent, Export as, Theme), mas aninhamento profundo prejudica a descoberta. <MenubarSubTrigger> acrescenta um chevron apontando para a direita automaticamente.

Acessibilidade

  • Padrão WAI-ARIA Menubar: a raiz carrega role="menubar"; triggers carregam role="menuitem" com aria-haspopup="menu" e aria-expanded; painéis de content carregam role="menu"; itens carregam role="menuitem", role="menuitemcheckbox" ou role="menuitemradio" conforme o caso.
  • Teclado entre menus: Tab entra na barra; ArrowLeft / ArrowRight caminham entre triggers (e continuam caminhando entre os contents dos menus abertos); ArrowDown / Enter abrem o trigger ativo; ArrowUp / ArrowDown movem entre itens dentro do content; ArrowRight abre um sub-trigger; ArrowLeft fecha um sub; Escape fecha o menu aberto e devolve o foco para o trigger.
  • Type-ahead: o Radix suporta type-ahead pela primeira letra dentro de cada menu, então digitar "S" pula para o primeiro item começando com S.
  • Dicas de atalho: <MenubarShortcut> é só visual. Conecte os bindings de teclado reais fora do componente (seu próprio handler a nível de documento).
  • Itens desabilitados: renderizam com aria-disabled="true" e são pulados na navegação por setas.

Relacionados

On this page