Components

Navigation menu

Rich hover-menu for site-level nav (marketing / docs sections). Radix-powered with an animated viewport that resizes to fit the current panel. Each trigger is h-9, rounded-md; hover/open use bg-accent + accent-foreground; the viewport uses shadow-sm.

Updated Jul 17, 2026 by Leonardo Posada

Anatomy

  1. 1
    NavigationMenu (root)

    The root that owns the viewport container. Renders the trigger list and the shared viewport below.

  2. 2
    NavigationMenuList

    Horizontal list of menu items. gap-1 between triggers.

  3. 3
    NavigationMenuTrigger

    One label in the top bar. h-9 rounded-md, hover/open bg-accent + accent-foreground. Optional trailing CaretDown that rotates on open.

  4. 4
    NavigationMenuLink

    A plain link that doesn't open a panel — use inside a NavigationMenuItem to represent a direct destination.

  5. 5
    NavigationMenuContent

    The panel that lives inside the shared viewport when a trigger opens. Free-form layout: single column, 2-column grid, featured card, etc.

  6. 6
    NavigationMenuViewport

    The shared floating surface (rounded-md, border, bg-popover, shadow-sm) that all panels render into. Auto-sizes to the active content.

  7. 7
    NavigationMenuIndicator

    Optional arrow above the viewport that follows the active trigger.

Content layouts

The viewport is a blank surface — the panel decides the layout. Five canonical shapes from the playground: Featured card, 2-column grid, List with title + description, Simple list, and List with icons.

Featured card + list
<NavigationMenuContent>
  <ul className="grid gap-3 p-4 md:w-[500px] md:grid-cols-[.75fr_1fr]">
    <li className="row-span-3">
      <a href="/" className="flex h-full flex-col justify-end rounded-md bg-muted/50 p-6 no-underline outline-none">
        <div className="text-lg font-medium">shadcn/ui</div>
        <p className="mt-2 text-sm text-muted-foreground">Beautifully designed components built with Tailwind CSS.</p>
      </a>
    </li>
    <ListRow title="Introduction" desc="Re-usable components built using Radix UI and Tailwind CSS." />
    <ListRow title="Installation" desc="How to install dependencies and structure your app." />
    <ListRow title="Typography" desc="Styles for headings, paragraphs, lists, etc." />
  </ul>
</NavigationMenuContent>
2-column grid
<NavigationMenuContent>
  <ul className="grid gap-3 p-4 md:w-[520px] md:grid-cols-2">
    {items.map((c) => <ListRow key={c.title} title={c.title} desc={c.desc} />)}
  </ul>
</NavigationMenuContent>
List with title + description
<NavigationMenuContent>
  <ul className="grid w-80 gap-1 p-2">
    {items.map((it) => <ListRow key={it.title} title={it.title} desc={it.desc} />)}
  </ul>
</NavigationMenuContent>
Simple list
<NavigationMenuContent>
  <ul className="grid w-64 gap-1 p-2">
    <ListRow title="Components" />
    <ListRow title="Documentation" />
    <ListRow title="Blocks" />
  </ul>
</NavigationMenuContent>
List with icons
<NavigationMenuContent>
  <ul className="grid w-64 gap-1 p-2">
    {items.map((it) => (
      <li key={it.title}>
        <NavigationMenuLink href="#" className="…flex items-center gap-2…">
          <it.icon weight="light" className="size-4 text-muted-foreground" />
          {it.title}
        </NavigationMenuLink>
      </li>
    ))}
  </ul>
</NavigationMenuContent>

States

Trigger states: Default, Hover (bg-accent + accent-foreground), Open (bg-accent + accent-foreground + CaretDown rotated 180°), Active (bg-accent when marked as current), Disabled (opacity-50, pointer-events-none).

Trigger states
<NavigationMenu>
  <NavigationMenuList>
    <NavigationMenuItem>
      <NavigationMenuLink className={navigationMenuTriggerStyle()}>Default</NavigationMenuLink>
    </NavigationMenuItem>
    <NavigationMenuItem>
      <NavigationMenuLink className={cn(navigationMenuTriggerStyle(), "bg-accent text-accent-foreground")}>Active</NavigationMenuLink>
    </NavigationMenuItem>
    <NavigationMenuItem>
      <NavigationMenuLink className={cn(navigationMenuTriggerStyle(), "opacity-50 pointer-events-none")}>Disabled</NavigationMenuLink>
    </NavigationMenuItem>
  </NavigationMenuList>
</NavigationMenu>
Not the Dashboard nav
This is a marketing / docs nav pattern. In Yuno's Dashboard the primary nav is always the Sidebar. Reach for NavigationMenu only when the prototype simulates a marketing site, docs portal, or public partner surface.

Recipes

Ready-to-copy compositions covering the most common Yuno usages of this atom.

Getting Started (featured card)

Left column is a brand card; right column stacks 3 titled items. The canonical shadcn/ui landing menu.

Components grid

2-column grid of items with title + description. Use when the menu enumerates many peers (products, features, docs sections).

Simple list

Single-column list of plain links, no descriptions. Use when the destinations are self-explanatory.

List with icons

Single-column list with a leading Phosphor icon per item. Use for status pickers, filters, or icon-annotated destinations.

Import

Copy this import line at the top of the file where you compose this atom.

Full compound + the CVA helper for standalone link triggers.
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
  navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu";

Props

Everything else from the underlying HTML or Radix primitive is forwarded via ...props.

PropTypeDefaultDescription
NavigationMenu.orientation"horizontal" | "vertical""horizontal"Trigger layout direction. Default matches marketing top-nav.
NavigationMenu.value / defaultValuestringControlled or uncontrolled open trigger key. Useful for programmatic control.
NavigationMenu.delayDurationnumber200How long the user must hover before a menu opens.
NavigationMenuTrigger.disabledbooleanfalseDims to opacity-50 and blocks the menu from opening.
NavigationMenuContent.classNamestringLayout the content freely (grid, columns, featured card). The viewport auto-resizes.
NavigationMenuLink.hrefstringDestination. Use for direct-link triggers (no dropdown) inside a NavigationMenuItem.
NavigationMenuLink.activebooleanfalseMarks the link as current. Applies data-[active] on the element.
navigationMenuTriggerStyle()() => stringCVA class helper to make a NavigationMenuLink look like a Trigger (used for standalone link items without a dropdown).
NavigationMenuViewportcomponentAuto-rendered inside NavigationMenu — do not mount manually.
NavigationMenuIndicatorcomponentOptional arrow above the viewport that follows the active trigger. Mount inside NavigationMenu if you want it.

When to use

  • Marketing sites with multi-column hover dropdowns.
  • Docs sites with rich sub-navigation panels.
  • Public partner surfaces that need a hover-first top nav.

When not to use

  • Dashboard shells — use Sidebar.
  • Simple links — use plain <a> or next/link.
  • Mobile-only prototypes — hover doesn't exist there.

Usage

Do
  • Keep each menu column focused on one topic.
  • Use NavigationMenuLink for each item so semantics stay correct.
  • Let the viewport auto-size — don't force widths on panels.
  • Keep the trigger label to one or two words.
Don't
  • Don't animate too aggressively — subtle fade works best.
  • Don't nest a NavigationMenu inside another — one level only.
  • Don't hide critical destinations behind hover — they need a visible link somewhere.

Related

Cross-links to atoms and patterns you may reach for next.

  • MenubarFor editor/desktop-app menus (File / Edit / View) instead of marketing hover-menus.
  • Dropdown menuFor a single trigger button that opens a compact action menu.
  • SidebarYuno's Dashboard nav lives here, not in a NavigationMenu.
  • CommandFor a searchable ⌘K palette instead of a hover-driven menu.