Navigation Menu
Nav primária de site de marketing com painéis ricos. Faça hover ou focus num trigger para abrir content multi-coluna sob a barra.
Visão geral
NavigationMenu é o primitivo de navegação primária de site de marketing: uma barra horizontal de triggers, cada um abrindo um painel de content rico sob a barra. Construído sobre o Radix NavigationMenu, ele implementa o padrão do Vercel / Stripe / Tailwind - "Products", "Solutions", "Pricing" com grids multi-coluna de links e blocos de features sob cada trigger.
Use o NavigationMenu quando o header também funciona como superfície de descoberta - os painéis mostram categorização e deixam os usuários navegar sem clicar através. Para navegação entre seções interna do app use Sidebar; para views irmãs dentro de uma página use Tabs; para menus de ação dentro de uma única tela use DropdownMenu. Evite aninhar overlays interativos (Dialog, Popover) dentro de um painel - o gerenciamento de focus fica frágil rápido.
Preview
'use client';import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger,} from '@gremorie/rx-navigation';export function NavigationMenuPreview() { return ( <NavigationMenu> <NavigationMenuList> <NavigationMenuItem> <NavigationMenuTrigger>Components</NavigationMenuTrigger> <NavigationMenuContent> <ul className="grid gap-2 p-4 w-[300px]"> <li> <NavigationMenuLink href="#">AI primitives</NavigationMenuLink> </li> <li> <NavigationMenuLink href="#">Forms</NavigationMenuLink> </li> <li> <NavigationMenuLink href="#">Charts</NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> );}Anatomia
NavigationMenu the root; auto-mounts a Viewport when viewport is on
├─ NavigationMenuList the horizontal list of items
│ └─ NavigationMenuItem one slot: trigger + panel, or a plain link
│ ├─ NavigationMenuTrigger the label that opens a content panel
│ ├─ NavigationMenuContent the dropdown panel (multi-column friendly)
│ │ └─ NavigationMenuLink a link, inside a panel or standalone
│ └─ navigationMenuTriggerStyle CVA helper to style plain links like triggers
├─ NavigationMenuIndicator pointer arrow that tracks the active trigger
└─ NavigationMenuViewport shared sliding container (auto-mounted)Instalação
bash npx gremorie@latest add rx-navigation-menu bash pnpm dlx gremorie@latest add rx-navigation-menu
bash yarn dlx gremorie@latest add rx-navigation-menu
bash bunx --bun gremorie@latest add rx-navigation-menu
Uso
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
} from "@gremorie/rx-navigation";
export function SiteNav() {
return (
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Products</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid w-[400px] gap-2 p-4">
<li>
<NavigationMenuLink href="/ai">AI primitives</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink href="/forms">Forms</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink href="/charts">Charts</NavigationMenuLink>
</li>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
);
}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
<NavigationMenu>
Container raiz. Envolve o NavigationMenu.Root do Radix.
| Prop | Type | Default | Description |
|---|---|---|---|
viewport | boolean | true | Quando true, monta <NavigationMenuViewport> automaticamente para que os painéis compartilhem um único container deslizante. Defina false para renderizar cada painel inline sob seu trigger. |
defaultValue | string | - | Menu inicialmente aberto, não controlado. |
value | string | - | Menu aberto controlado. |
onValueChange | (value: string) => void | - | Dispara quando o menu aberto muda. |
delayDuration | number | 200 | Delay de abertura por hover em milissegundos. |
skipDelayDuration | number | 300 | Janela em que passar o hover entre triggers pula o delay. |
dir | "ltr" | "rtl" | "ltr" | Direção de leitura. |
orientation | "horizontal" | "vertical" | "horizontal" | Eixo de layout. |
<NavigationMenuList>
Container para os triggers. Envolve o NavigationMenu.List do Radix.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof NavigationMenu.List> | - | Props padrão de list. |
<NavigationMenuItem>
Um único menu (trigger mais content) dentro da list. Envolve o NavigationMenu.Item do Radix.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | Identificador usado pelo value / onValueChange controlado do Root. |
<NavigationMenuTrigger>
O botão da barra. Envolve o NavigationMenu.Trigger do Radix. Acrescenta automaticamente um ChevronDown que gira 180 graus quando o menu está aberto.
| Prop | Type | Default | Description |
|---|---|---|---|
disabled | boolean | false | Desabilita este trigger. |
<NavigationMenuContent>
O painel rico revelado abaixo do trigger. Envolve o NavigationMenu.Content do Radix. Vem com classes de animação sensíveis a movimento para as quatro direções de enter / exit (from-start, from-end, to-start, to-end).
| Prop | Type | Default | Description |
|---|---|---|---|
forceMount | boolean | false | Força o painel no DOM mesmo quando inativo. |
<NavigationMenuLink>
Um link dentro do painel de content. Envolve o NavigationMenu.Link do Radix.
| Prop | Type | Default | Description |
|---|---|---|---|
active | boolean | false | Marca o link como a localização atual; estiliza via data-[active=true]. |
onSelect | (event: Event) => void | - | Dispara quando o link é ativado. Chame event.preventDefault() para manter o menu aberto. |
asChild | boolean | false | Encaminha as props para o único filho (use com o Link do framework). |
href | string | - | Alvo da âncora. |
<NavigationMenuViewport>
O container deslizante compartilhado que hospeda qualquer painel de content ativo. Montado automaticamente pelo Root quando viewport={true}. Renderize manualmente apenas quando você precisar de controle preciso sobre sua posição.
| Prop | Type | Default | Description |
|---|---|---|---|
forceMount | boolean | false | Força o viewport no DOM mesmo quando nenhum menu está aberto. |
<NavigationMenuIndicator>
Seta indicadora opcional que acompanha o trigger ativo. Renderize como irmã da list quando você quiser a pista visual.
| Prop | Type | Default | Description |
|---|---|---|---|
forceMount | boolean | false | Força o indicador no DOM quando nenhum menu está ativo. |
navigationMenuTriggerStyle
Função cva exportada. Use para estilizar links da barra standalone (links sem painel de content) para que combinem com a aparência do trigger.
<NavigationMenuItem>
<NavigationMenuLink href="/pricing" className={navigationMenuTriggerStyle()}>
Pricing
</NavigationMenuLink>
</NavigationMenuItem>Composição
<NavigationMenu>detém o estado de aberto e (comviewport={true}) monta o viewport compartilhado.<NavigationMenuList>segura os triggers horizontalmente.- Cada
<NavigationMenuItem>envolve um<NavigationMenuTrigger>mais um<NavigationMenuContent>. Para links de barra standalone (sem painel) envolva um<NavigationMenuLink>comnavigationMenuTriggerStyle(). - Dentro do content, use um grid
<ul>/<li>com elementos<NavigationMenuLink>- o layout do painel é seu para compor.
Quando viewport={true} (default), todos os painéis de content compartilham um único container deslizante que redimensiona entre menus. Quando viewport={false}, cada <NavigationMenuContent> renderiza inline sob seu próprio trigger - útil quando os painéis vivem dentro de um card com largura fixa.
Variações
Links simples
'use client';import { NavigationMenu, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, navigationMenuTriggerStyle,} from '@gremorie/rx-navigation';export function NavigationMenuLinksPreview() { return ( <NavigationMenu> <NavigationMenuList> <NavigationMenuItem> <NavigationMenuLink href="#" className={navigationMenuTriggerStyle()}> Products </NavigationMenuLink> </NavigationMenuItem> <NavigationMenuItem> <NavigationMenuLink href="#" className={navigationMenuTriggerStyle()}> Pricing </NavigationMenuLink> </NavigationMenuItem> <NavigationMenuItem> <NavigationMenuLink href="#" className={navigationMenuTriggerStyle()}> Docs </NavigationMenuLink> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> );}Use como uma barra de header quando cada entrada é um link direto e nenhum painel é necessário. Aplique navigationMenuTriggerStyle() a cada <NavigationMenuLink> para que os links crus combinem com a aparência do trigger.
Mega menu com grid de content
'use client';import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger,} from '@gremorie/rx-navigation';export function NavigationMenuMegaPreview() { return ( <NavigationMenu> <NavigationMenuList> <NavigationMenuItem> <NavigationMenuTrigger>Products</NavigationMenuTrigger> <NavigationMenuContent> <ul className="grid w-[500px] grid-cols-2 gap-2 p-4"> <li> <NavigationMenuLink href="#" className="space-y-1"> <div className="font-medium">AI primitives</div> <p className="text-sm text-muted-foreground"> Chat, prompt, response, tool. </p> </NavigationMenuLink> </li> <li> <NavigationMenuLink href="#" className="space-y-1"> <div className="font-medium">Forms</div> <p className="text-sm text-muted-foreground"> Inputs, selects, validation. </p> </NavigationMenuLink> </li> <li> <NavigationMenuLink href="#" className="space-y-1"> <div className="font-medium">Charts</div> <p className="text-sm text-muted-foreground"> Sequential, categorical, divergent palettes. </p> </NavigationMenuLink> </li> <li> <NavigationMenuLink href="#" className="space-y-1"> <div className="font-medium">Navigation</div> <p className="text-sm text-muted-foreground"> Tabs, sidebar, breadcrumb. </p> </NavigationMenuLink> </li> </ul> </NavigationMenuContent> </NavigationMenuItem> </NavigationMenuList> </NavigationMenu> );}Use como a superfície de descoberta de um site de marketing. O grid de duas colunas dá conta de landings de categoria com descrições curtas sob cada link.
Painéis inline (sem viewport)
<NavigationMenu viewport={false}>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Resources</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid w-[280px] gap-1 p-3">
<li>
<NavigationMenuLink href="/blog">Blog</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink href="/guides">Guides</NavigationMenuLink>
</li>
<li>
<NavigationMenuLink href="/changelog">Changelog</NavigationMenuLink>
</li>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>Use quando cada painel tem sua própria largura e deve descer logo abaixo do seu trigger sem o viewport deslizante compartilhado.
Acessibilidade
- Padrão WAI-ARIA Menubar: triggers carregam
aria-expandedearia-controls; painéis de content carregamaria-labelledbyapontando para seu trigger. - Teclado:
Tabentra na barra;ArrowLeft/ArrowRightmovem entre triggers;ArrowDownouEnterabre o painel do trigger ativo;Escapefecha o painel aberto e devolve o foco para o trigger;Tabde dentro de um painel move para o content do painel e eventualmente para fora do menu. - Gerenciamento de focus: abrir um painel não rouba o foco do trigger; os usuários decidem quando entrar no painel. Dentro do painel,
Tabcaminha pelos links em ordem do DOM. - Triggers desabilitados: renderizam com
aria-disabled="true"e são pulados na navegação por setas. - Link ativo: passe
activeem<NavigationMenuLink>para definirdata-active="true"para estilização de localização atual.
Relacionados
- Sidebar - navegação entre seções interna do app.
- DropdownMenu - menus de ação de trigger único.
- Menubar - padrão File / Edit / View de app desktop.