KDS
Navigation

NavigationMenu

Header primário de marketing com painéis ricos — padrão Vercel/Stripe.

Overview

NavigationMenu é o menu primário de header de sites de marketing e produto — Products / Solutions / Pricing / Docs com painéis ricos sob cada gatilho. É o padrão que Vercel, Stripe, Linear e Tailwind usam para revelar uma estrutura de produto sem comprometer a hierarquia visual da homepage.

Para navegação app-internal (sidebar, settings) use Sidebar. Para menus de ação dentro de uma página (ex.: "+ New") use DropdownMenu. Não aninhe overlays interativos (Dialog, Popover) dentro de um painel — o focus management fica frágil rapidamente.

Preview
Trigger com painel + links diretos.

Anatomy

<NavigationMenu>
  <NavigationMenuList>
    <NavigationMenuItem>
      <NavigationMenuTrigger>Products</NavigationMenuTrigger>
      <NavigationMenuContent>
        <NavigationMenuLink href="/a">…</NavigationMenuLink>
      </NavigationMenuContent>
    </NavigationMenuItem>
    <NavigationMenuItem>
      <NavigationMenuLink className={navigationMenuTriggerStyle()}>
        Pricing
      </NavigationMenuLink>
    </NavigationMenuItem>
  </NavigationMenuList>
</NavigationMenu>

Itens podem ser triggers com painel ou links diretos. Use navigationMenuTriggerStyle() para alinhar o estilo de links diretos com triggers.

Subcomponents

ComponenteDescrição
NavigationMenuRaiz; aceita viewport={false} para ancorar painéis sob cada item.
NavigationMenuList<ul> horizontal dos triggers.
NavigationMenuItem<li> que abriga trigger + content.
NavigationMenuTriggerBotão que abre o painel; renderiza chevron de affordance.
NavigationMenuContentPainel que aparece sob o trigger ativo.
NavigationMenuLinkLink — direto ou dentro de um painel.
NavigationMenuIndicatorSetinha animada que segue o trigger ativo.
NavigationMenuViewportContainer que renderiza o painel.
navigationMenuTriggerStyleHelper CVA — o mesmo estilo do trigger para links diretos.

Usage

import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
  navigationMenuTriggerStyle
} from "@kalvner/kds/navigation/navigation-menu";

export function HeaderNav() {
  return (
    <NavigationMenu>
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuTrigger>Products</NavigationMenuTrigger>
          <NavigationMenuContent>
            <ul className="grid w-[400px] gap-2 p-3 md:grid-cols-2">…</ul>
          </NavigationMenuContent>
        </NavigationMenuItem>
        <NavigationMenuItem>
          <NavigationMenuLink className={navigationMenuTriggerStyle()} href="/pricing">
            Pricing
          </NavigationMenuLink>
        </NavigationMenuItem>
      </NavigationMenuList>
    </NavigationMenu>
  );
}

Variants

Rich panel
Hero à esquerda + lista de links à direita — padrão "categorias do produto".

When to use

  • Header primário em sites de marketing e landing pages.
  • Quando o produto tem múltiplas linhas e cada uma precisa de contexto além do nome (descrição, ícone, mini-hero).
  • Para navegação que mistura links diretos + grupos com painel.

When not to use

  • Para nav interna de aplicação — use Sidebar.
  • Para alternar views da mesma página — use Tabs.
  • Para mobile-first sem fallback — em telas estreitas, transforme no padrão drawer + accordion.
  • Para action menus — use DropdownMenu.

Best practices

  • Painéis curtos. 3–6 itens por painel; passou disso, repense a categorização.
  • Hero opcional, não decorativo. Use a área row-span-3 quando o link merece destaque (link de produto principal, demo). Caso contrário, deixe lista plana.
  • Mobile fallback. Em mobile, troque por Drawer + Accordion (links agrupados em sections expansíveis).
  • Não aninhe overlays. Dialog dentro de NavigationMenu quebra focus. Use o painel como teaser, leve para a página completa.
  • Active state via router. Marque o item ativo com data-active="true" no NavigationMenuLink correspondente.

Accessibility

ConcernComportamento
RolesRadix aplica role="menubar" na lista, role="menuitem" nos triggers, e gerencia aria-expanded.
KeyboardSetas movem entre triggers; Enter/Space abre painel; Esc fecha; Tab saindo do painel mantém ordem.
FocusFoco entra no painel quando aberto; Esc retorna ao trigger.
Screen readerTriggers anunciados como "Products, expanded/collapsed, menu".
  • Sidebar — navegação interna de aplicação.
  • Menubar — menu bar em apps desktop-style.
  • Tabs — alternar views dentro de um escopo.

On this page