Skip to content
Dethink Components

ComponentsNavigationMenu

NavigationMenu

Group page links in a menu with optional dropdown panels.

On this page

Use this component from the local workspace package. Follow the setup guide first. A public npm package and registry are not available yet.

View registry files

Import the component into your page or component file.

Usage
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuIndicator,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
  NavigationMenuViewport,
} from "@dethink/components";

NavigationMenu keeps links as links. Triggers are disclosure buttons with aria-expanded, and panels stay in the navigation's tab order.

Current, disabled, and external states on a persistent top navigation.

Examples that combine components for common tasks.

Brand navbar

A full marketing navbar: brand logo, icon-led menu with rich flyouts and the animated indicator, plus a theme toggle, login, and call-to-action cluster. When the bar gets narrow, the burger expands an integrated panel with accordion submenus โ€” no overlay.

Dethink
Show sourceexamples/navigation-menu/brand-navbar.tsx
examples/navigation-menu/brand-navbar.tsx
"use client";

import { useState } from "react";
import {
  Button,
  IconButton,
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuDescription,
  NavigationMenuFeaturedItem,
  NavigationMenuIndicator,
  NavigationMenuItem,
  NavigationMenuLabel,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuSection,
  NavigationMenuSeparator,
  NavigationMenuTrigger,
} from "@dethink/components";
import {
  BarChart3,
  BookOpen,
  Bot,
  CreditCard,
  LifeBuoy,
  Menu,
  Moon,
  Newspaper,
  Rocket,
  Sparkles,
  Sun,
  Workflow,
  X,
} from "lucide-react";

const productLinks = [
  {
    href: "#analytics",
    label: "Analytics",
    description: "Usage dashboards for every workspace.",
    icon: BarChart3,
  },
  {
    href: "#automation",
    label: "Automation",
    description: "Build workflows that react to events.",
    icon: Workflow,
  },
  {
    href: "#assistant",
    label: "AI Assistant",
    description: "Ask questions across all your data.",
    icon: Bot,
  },
];

const resourceLinks = [
  {
    href: "#docs",
    label: "Documentation",
    description: "Guides, API reference, and recipes.",
    icon: BookOpen,
  },
  {
    href: "#blog",
    label: "Blog",
    description: "Product updates and engineering notes.",
    icon: Newspaper,
  },
  {
    href: "#support",
    label: "Support",
    description: "Talk to a human when you need one.",
    icon: LifeBuoy,
  },
];

function BrandLogo() {
  return (
    <a
      href="#home"
      className="focus-visible:ring-ring focus-visible:ring-offset-background flex shrink-0 items-center gap-2 rounded-md focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
    >
      <span
        aria-hidden="true"
        className="from-primary to-primary/60 text-primary-foreground flex size-8 items-center justify-center rounded-lg bg-gradient-to-br shadow-sm"
      >
        <Sparkles className="size-4" />
      </span>
      <span className="text-foreground text-base font-semibold tracking-tight">
        Dethink
      </span>
    </a>
  );
}

/**
 * The same destinations power both layouts. In the stacked (mobile) layout the
 * flyout panels are restyled into in-place accordions: the item stacks, the
 * trigger spans the row, and the content swaps its absolute side panel for a
 * static full-width block.
 */
function BrandNavItems({ stacked = false }: { stacked?: boolean }) {
  const itemClass = stacked ? "w-full flex-col items-stretch" : undefined;
  const triggerClass = stacked
    ? "w-full [&>[data-slot=navigation-menu-trigger-icon]]:ms-auto"
    : undefined;
  const contentClass = stacked
    ? "static w-full max-w-none flex-col border-0 bg-transparent p-0 ps-[var(--dt-space-2)] pt-[var(--dt-space-1)] shadow-none"
    : undefined;
  const linkClass = stacked ? "w-full" : undefined;

  return (
    <>
      <NavigationMenuItem className={itemClass} value="product">
        <NavigationMenuTrigger className={triggerClass}>
          <Rocket aria-hidden="true" className="text-muted-foreground size-4" />
          Product
        </NavigationMenuTrigger>
        <NavigationMenuContent className={contentClass}>
          <NavigationMenuFeaturedItem
            href="#platform"
            className={stacked ? "w-full" : undefined}
          >
            Platform overview
            <NavigationMenuDescription>
              Analytics, automation, and AI in one workspace.
            </NavigationMenuDescription>
          </NavigationMenuFeaturedItem>
          {stacked ? null : <NavigationMenuSeparator orientation="vertical" />}
          <NavigationMenuSection className={stacked ? "w-full" : undefined}>
            <NavigationMenuLabel>Products</NavigationMenuLabel>
            {productLinks.map(({ href, label, description, icon: Icon }) => (
              <NavigationMenuLink
                key={href}
                href={href}
                icon={<Icon aria-hidden="true" />}
              >
                {label}
                <NavigationMenuDescription>
                  {description}
                </NavigationMenuDescription>
              </NavigationMenuLink>
            ))}
          </NavigationMenuSection>
        </NavigationMenuContent>
      </NavigationMenuItem>

      <NavigationMenuItem className={itemClass} value="resources">
        <NavigationMenuTrigger className={triggerClass}>
          <BookOpen
            aria-hidden="true"
            className="text-muted-foreground size-4"
          />
          Resources
        </NavigationMenuTrigger>
        <NavigationMenuContent className={contentClass}>
          <NavigationMenuSection className={stacked ? "w-full" : undefined}>
            <NavigationMenuLabel>Learn</NavigationMenuLabel>
            {resourceLinks.map(({ href, label, description, icon: Icon }) => (
              <NavigationMenuLink
                key={href}
                href={href}
                icon={<Icon aria-hidden="true" />}
              >
                {label}
                <NavigationMenuDescription>
                  {description}
                </NavigationMenuDescription>
              </NavigationMenuLink>
            ))}
          </NavigationMenuSection>
        </NavigationMenuContent>
      </NavigationMenuItem>

      <NavigationMenuItem className={stacked ? "w-full" : undefined}>
        <NavigationMenuLink
          current
          href="#pricing"
          icon={<CreditCard aria-hidden="true" />}
          className={linkClass}
        >
          Pricing
        </NavigationMenuLink>
      </NavigationMenuItem>
    </>
  );
}

export function NavigationMenuBrandNavbar() {
  // Local to the example โ€” a real app would drive this from its theme provider.
  const [darkPreview, setDarkPreview] = useState(false);
  const [mobileOpen, setMobileOpen] = useState(false);
  const ThemeIcon = darkPreview ? Moon : Sun;

  return (
    // The container query keeps the collapse tied to the navbar's own width,
    // so the example adapts to whatever column hosts it.
    <div className="@container min-h-[26rem]">
      <header className="border-border bg-background/80 supports-[backdrop-filter]:bg-background/60 rounded-xl border shadow-sm backdrop-blur">
        <div className="flex h-14 items-center gap-2 px-3">
          <BrandLogo />

          {/* Wide: icon-led navigation with the animated indicator. The panel
              max-width is capped so flyouts stay inside the navbar column. */}
          <NavigationMenu
            aria-label="Main"
            className="[--dt-navigation-menu-content-max-width:34rem] @max-3xl:hidden"
          >
            <NavigationMenuList>
              <BrandNavItems />
              <NavigationMenuIndicator />
            </NavigationMenuList>
          </NavigationMenu>

          <div className="ml-auto flex items-center gap-1.5">
            <IconButton
              aria-label={
                darkPreview ? "Switch to light theme" : "Switch to dark theme"
              }
              aria-pressed={darkPreview}
              variant="ghost"
              size="sm"
              onClick={() => setDarkPreview((previous) => !previous)}
            >
              <ThemeIcon aria-hidden="true" />
            </IconButton>

            <span
              aria-hidden="true"
              className="bg-border mx-1 h-5 w-px @max-md:hidden"
            />

            <Button variant="ghost" size="sm" className="@max-md:hidden">
              Log in
            </Button>
            <Button size="sm">Get started</Button>

            {/* Narrow: the burger expands an integrated panel below the bar โ€”
                no overlay, the navbar simply grows. */}
            <IconButton
              aria-label={mobileOpen ? "Close navigation" : "Open navigation"}
              aria-expanded={mobileOpen}
              aria-controls="brand-navbar-mobile-panel"
              variant="ghost"
              size="sm"
              className="@3xl:hidden"
              onClick={() => setMobileOpen((previous) => !previous)}
            >
              {mobileOpen ? (
                <X aria-hidden="true" />
              ) : (
                <Menu aria-hidden="true" />
              )}
            </IconButton>
          </div>
        </div>

        <div
          id="brand-navbar-mobile-panel"
          hidden={!mobileOpen}
          className="border-border border-t @3xl:hidden"
        >
          <div className="space-y-3 px-3 py-3">
            <NavigationMenu
              aria-label="Main"
              orientation="vertical"
              variant="quiet"
              className="w-full"
            >
              <NavigationMenuList className="w-full">
                <BrandNavItems stacked />
              </NavigationMenuList>
            </NavigationMenu>
            {/* Mirror the login action while the bar hides it. */}
            <div className="border-border border-t pt-3 @md:hidden">
              <Button variant="outline" size="sm" className="w-full">
                Log in
              </Button>
            </div>
          </div>
        </div>
      </header>
    </div>
  );
}

Product navigation

Rich flyout panels with a featured card, grouped links, icons, descriptions, and the animated indicator.

Show sourceexamples/navigation-menu/product-nav.tsx
examples/navigation-menu/product-nav.tsx
"use client";

import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuDescription,
  NavigationMenuFeaturedItem,
  NavigationMenuIndicator,
  NavigationMenuItem,
  NavigationMenuLabel,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuSection,
  NavigationMenuSeparator,
  NavigationMenuTrigger,
} from "@dethink/components";
import { BarChart3, Workflow } from "lucide-react";

export function NavigationMenuProductNav() {
  return (
    <div className="min-h-[22rem]">
      <NavigationMenu aria-label="Product">
        <NavigationMenuList>
          <NavigationMenuItem value="platform">
            <NavigationMenuTrigger>Platform</NavigationMenuTrigger>
            <NavigationMenuContent>
              <NavigationMenuFeaturedItem href="#platform">
                Platform overview
                <NavigationMenuDescription>
                  Analytics, automation, and reporting in one workspace.
                </NavigationMenuDescription>
              </NavigationMenuFeaturedItem>
              <NavigationMenuSeparator orientation="vertical" />
              <NavigationMenuSection>
                <NavigationMenuLabel>Products</NavigationMenuLabel>
                <NavigationMenuLink
                  href="#analytics"
                  icon={<BarChart3 aria-hidden="true" />}
                >
                  Analytics
                  <NavigationMenuDescription>
                    Usage dashboards for every workspace.
                  </NavigationMenuDescription>
                </NavigationMenuLink>
                <NavigationMenuLink
                  href="#automation"
                  icon={<Workflow aria-hidden="true" />}
                >
                  Automation
                  <NavigationMenuDescription>
                    Build workflows that react to events.
                  </NavigationMenuDescription>
                </NavigationMenuLink>
              </NavigationMenuSection>
            </NavigationMenuContent>
          </NavigationMenuItem>
          <NavigationMenuItem value="solutions">
            <NavigationMenuTrigger>Solutions</NavigationMenuTrigger>
            <NavigationMenuContent>
              <NavigationMenuSection>
                <NavigationMenuLabel>By team</NavigationMenuLabel>
                <NavigationMenuLink href="#product-teams">
                  Product teams
                </NavigationMenuLink>
                <NavigationMenuLink href="#data-teams">
                  Data teams
                </NavigationMenuLink>
              </NavigationMenuSection>
            </NavigationMenuContent>
          </NavigationMenuItem>
          <NavigationMenuItem>
            <NavigationMenuLink current href="#pricing">
              Pricing
            </NavigationMenuLink>
          </NavigationMenuItem>
          <NavigationMenuIndicator />
        </NavigationMenuList>
      </NavigationMenu>
    </div>
  );
}

App topbar with mobile handoff

A compact quiet nav on desktop; on small screens the same links hand off to a Dialog. Resize the viewport to see the collapse.

Acme Cloud
workspace: prod
Show sourceexamples/navigation-menu/app-topbar.tsx
examples/navigation-menu/app-topbar.tsx
"use client";

import {
  Dialog,
  DialogContent,
  DialogTitle,
  DialogTrigger,
  NavigationMenu,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
} from "@dethink/components";
import { Menu } from "lucide-react";

const sections = [
  { href: "#dashboard", label: "Dashboard", current: true },
  { href: "#deployments", label: "Deployments", current: false },
  { href: "#monitoring", label: "Monitoring", current: false },
  { href: "#team", label: "Team", current: false },
];

export function NavigationMenuAppTopbar() {
  return (
    <header className="border-border bg-muted/30 flex items-center justify-between gap-4 rounded-md border px-4 py-2">
      <span className="text-foreground text-sm font-semibold">Acme Cloud</span>

      {/* Desktop: persistent quiet nav. */}
      <NavigationMenu
        aria-label="Dashboard"
        variant="quiet"
        size="sm"
        className="max-md:hidden"
      >
        <NavigationMenuList>
          {sections.map((section) => (
            <NavigationMenuItem key={section.href}>
              <NavigationMenuLink current={section.current} href={section.href}>
                {section.label}
              </NavigationMenuLink>
            </NavigationMenuItem>
          ))}
        </NavigationMenuList>
      </NavigationMenu>

      {/* Mobile: the same links hand off to a Dialog. NavigationMenu stays a
          navigation primitive โ€” the Dialog owns the overlay behavior. */}
      <div className="md:hidden">
        <Dialog>
          <DialogTrigger
            aria-label="Open navigation"
            size="icon"
            variant="outline"
          >
            <Menu aria-hidden="true" className="size-4" />
          </DialogTrigger>
          <DialogContent>
            <DialogTitle>Navigate</DialogTitle>
            <div className="px-[var(--dt-space-6)] pb-[var(--dt-space-6)]">
              <NavigationMenu
                aria-label="Dashboard"
                orientation="vertical"
                variant="quiet"
              >
                <NavigationMenuList>
                  {sections.map((section) => (
                    <NavigationMenuItem key={section.href}>
                      <NavigationMenuLink
                        current={section.current}
                        href={section.href}
                      >
                        {section.label}
                      </NavigationMenuLink>
                    </NavigationMenuItem>
                  ))}
                </NavigationMenuList>
              </NavigationMenu>
            </div>
          </DialogContent>
        </Dialog>
      </div>

      <span className="text-muted-foreground text-sm max-md:hidden">
        workspace: prod
      </span>
    </header>
  );
}

Mobile navigation drawer

A phone-sized in-page drawer: a disclosure button toggles the panel, and the vertical menu restyles its flyout into an accordion โ€” links, icons, current state, and auth actions stay intact.

Show sourceexamples/navigation-menu/mobile-drawer.tsx
examples/navigation-menu/mobile-drawer.tsx
"use client";

import { useState } from "react";
import {
  Button,
  IconButton,
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuDescription,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuSection,
  NavigationMenuTrigger,
} from "@dethink/components";
import {
  BarChart3,
  Bot,
  CreditCard,
  Home,
  LifeBuoy,
  Menu,
  Sparkles,
  Workflow,
  X,
} from "lucide-react";

/**
 * A self-contained mobile navigation drawer: a disclosure button toggles an
 * in-page panel (no overlay, so no Dialog needed), and the vertical
 * NavigationMenu turns its flyout into an accordion by restyling
 * NavigationMenuContent to flow in place.
 */
export function NavigationMenuMobileDrawer() {
  const [open, setOpen] = useState(true);

  return (
    <div className="border-border bg-background mx-auto w-full max-w-[22rem] overflow-hidden rounded-2xl border shadow-sm">
      <div className="flex h-14 items-center justify-between px-4">
        <a
          href="#home"
          className="focus-visible:ring-ring focus-visible:ring-offset-background flex items-center gap-2 rounded-md focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
        >
          <span
            aria-hidden="true"
            className="from-primary to-primary/60 text-primary-foreground flex size-7 items-center justify-center rounded-lg bg-gradient-to-br"
          >
            <Sparkles className="size-3.5" />
          </span>
          <span className="text-foreground text-sm font-semibold tracking-tight">
            Dethink
          </span>
        </a>
        <IconButton
          aria-label={open ? "Close navigation" : "Open navigation"}
          aria-expanded={open}
          aria-controls="mobile-drawer-panel"
          variant="ghost"
          size="sm"
          onClick={() => setOpen((previous) => !previous)}
        >
          {open ? <X aria-hidden="true" /> : <Menu aria-hidden="true" />}
        </IconButton>
      </div>

      <div
        id="mobile-drawer-panel"
        hidden={!open}
        className="border-border border-t"
      >
        <div className="space-y-4 px-3 py-4">
          <NavigationMenu
            aria-label="Main"
            orientation="vertical"
            variant="quiet"
            className="w-full"
          >
            <NavigationMenuList className="w-full">
              <NavigationMenuItem className="w-full">
                <NavigationMenuLink
                  current
                  href="#home"
                  icon={<Home aria-hidden="true" />}
                  className="w-full"
                >
                  Home
                </NavigationMenuLink>
              </NavigationMenuItem>

              {/* The flyout becomes an accordion: className swaps the
                  absolute side-panel for a static, full-width block. */}
              <NavigationMenuItem
                className="w-full flex-col items-stretch"
                value="products"
              >
                <NavigationMenuTrigger className="w-full justify-between">
                  Products
                </NavigationMenuTrigger>
                <NavigationMenuContent className="static w-full max-w-none border-0 bg-transparent p-0 ps-[var(--dt-space-2)] shadow-none">
                  <NavigationMenuSection className="w-full">
                    <NavigationMenuLink
                      href="#analytics"
                      icon={<BarChart3 aria-hidden="true" />}
                    >
                      Analytics
                      <NavigationMenuDescription>
                        Usage dashboards for every workspace.
                      </NavigationMenuDescription>
                    </NavigationMenuLink>
                    <NavigationMenuLink
                      href="#automation"
                      icon={<Workflow aria-hidden="true" />}
                    >
                      Automation
                      <NavigationMenuDescription>
                        Build workflows that react to events.
                      </NavigationMenuDescription>
                    </NavigationMenuLink>
                    <NavigationMenuLink
                      href="#assistant"
                      icon={<Bot aria-hidden="true" />}
                    >
                      AI Assistant
                      <NavigationMenuDescription>
                        Ask questions across all your data.
                      </NavigationMenuDescription>
                    </NavigationMenuLink>
                  </NavigationMenuSection>
                </NavigationMenuContent>
              </NavigationMenuItem>

              <NavigationMenuItem className="w-full">
                <NavigationMenuLink
                  href="#pricing"
                  icon={<CreditCard aria-hidden="true" />}
                  className="w-full"
                >
                  Pricing
                </NavigationMenuLink>
              </NavigationMenuItem>
              <NavigationMenuItem className="w-full">
                <NavigationMenuLink
                  external
                  href="https://status.example.com"
                  icon={<LifeBuoy aria-hidden="true" />}
                  className="w-full"
                >
                  Status
                </NavigationMenuLink>
              </NavigationMenuItem>
            </NavigationMenuList>
          </NavigationMenu>

          <div className="border-border space-y-2 border-t pt-4">
            <Button variant="outline" size="sm" className="w-full">
              Log in
            </Button>
            <Button size="sm" className="w-full">
              Get started
            </Button>
          </div>
        </div>
      </div>
    </div>
  );
}

Documentation hub

Underline variant with grouped guide flyouts and aria-current=location for the active page.

Show sourceexamples/navigation-menu/docs-hub.tsx
examples/navigation-menu/docs-hub.tsx
"use client";

import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuDescription,
  NavigationMenuItem,
  NavigationMenuLabel,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuSection,
  NavigationMenuSeparator,
  NavigationMenuTrigger,
} from "@dethink/components";

export function NavigationMenuDocsHub() {
  return (
    <div className="min-h-[20rem]">
      <NavigationMenu aria-label="Documentation" variant="underline">
        <NavigationMenuList>
          <NavigationMenuItem value="guides">
            <NavigationMenuTrigger>Guides</NavigationMenuTrigger>
            <NavigationMenuContent>
              <NavigationMenuSection>
                <NavigationMenuLabel>Getting started</NavigationMenuLabel>
                <NavigationMenuLink current="location" href="#install">
                  Installation
                  <NavigationMenuDescription>
                    Registry setup and base tokens.
                  </NavigationMenuDescription>
                </NavigationMenuLink>
                <NavigationMenuLink href="#theming">
                  Theming
                  <NavigationMenuDescription>
                    Light, dark, density, and brand palettes.
                  </NavigationMenuDescription>
                </NavigationMenuLink>
              </NavigationMenuSection>
              <NavigationMenuSeparator orientation="vertical" />
              <NavigationMenuSection>
                <NavigationMenuLabel>Recipes</NavigationMenuLabel>
                <NavigationMenuLink href="#forms">Forms</NavigationMenuLink>
                <NavigationMenuLink href="#tables">Tables</NavigationMenuLink>
                <NavigationMenuLink href="#navigation">
                  Navigation
                </NavigationMenuLink>
              </NavigationMenuSection>
            </NavigationMenuContent>
          </NavigationMenuItem>
          <NavigationMenuItem value="reference">
            <NavigationMenuTrigger>Reference</NavigationMenuTrigger>
            <NavigationMenuContent>
              <NavigationMenuSection>
                <NavigationMenuLink href="#api">
                  Component API
                </NavigationMenuLink>
                <NavigationMenuLink href="#tokens">Tokens</NavigationMenuLink>
              </NavigationMenuSection>
            </NavigationMenuContent>
          </NavigationMenuItem>
          <NavigationMenuItem>
            <NavigationMenuLink href="#changelog">Changelog</NavigationMenuLink>
          </NavigationMenuItem>
        </NavigationMenuList>
      </NavigationMenu>
    </div>
  );
}

Dashboard composition

A quiet topbar plus a vertical section nav composing an app shell โ€” without absorbing Sidebar's job.

Insights

Revenue report

Updated from pipeline run #428.

Two NavigationMenu instances compose the shell: a quiet topbar for workspace areas and a vertical section list for the active report. A full application shell with a collapsible sidebar stays out of scope for NavigationMenu โ€” that is the future Sidebar component.

Show sourceexamples/navigation-menu/dashboard.tsx
examples/navigation-menu/dashboard.tsx
"use client";

import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
  NavigationMenu,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
} from "@dethink/components";

export function NavigationMenuDashboard() {
  return (
    <div className="space-y-4">
      <header className="border-border bg-muted/30 flex items-center justify-between gap-4 rounded-md border px-4 py-2">
        <span className="text-foreground text-sm font-semibold">Insights</span>
        <NavigationMenu aria-label="Workspace areas" size="sm" variant="quiet">
          <NavigationMenuList>
            <NavigationMenuItem>
              <NavigationMenuLink href="#home">Home</NavigationMenuLink>
            </NavigationMenuItem>
            <NavigationMenuItem>
              <NavigationMenuLink current href="#reports">
                Reports
              </NavigationMenuLink>
            </NavigationMenuItem>
            <NavigationMenuItem>
              <NavigationMenuLink href="#alerts">Alerts</NavigationMenuLink>
            </NavigationMenuItem>
          </NavigationMenuList>
        </NavigationMenu>
      </header>

      <div className="grid gap-4 md:grid-cols-[12rem_minmax(0,1fr)]">
        <NavigationMenu
          aria-label="Report sections"
          orientation="vertical"
          size="sm"
          variant="quiet"
        >
          <NavigationMenuList>
            <NavigationMenuItem>
              <NavigationMenuLink current="location" href="#revenue">
                Revenue
              </NavigationMenuLink>
            </NavigationMenuItem>
            <NavigationMenuItem>
              <NavigationMenuLink href="#retention">
                Retention
              </NavigationMenuLink>
            </NavigationMenuItem>
            <NavigationMenuItem>
              <NavigationMenuLink href="#usage">Usage</NavigationMenuLink>
            </NavigationMenuItem>
          </NavigationMenuList>
        </NavigationMenu>

        <Card>
          <CardHeader>
            <CardTitle>Revenue report</CardTitle>
            <CardDescription>Updated from pipeline run #428.</CardDescription>
          </CardHeader>
          <CardContent>
            <p className="text-muted-foreground text-sm">
              Two NavigationMenu instances compose the shell: a quiet topbar for
              workspace areas and a vertical section list for the active report.
              A full application shell with a collapsible sidebar stays out of
              scope for NavigationMenu โ€” that is the future Sidebar component.
            </p>
          </CardContent>
        </Card>
      </div>
    </div>
  );
}

Overflow collapse

Secondary destinations collapse behind a More disclosure on narrow screens and render inline when space allows.

Show sourceexamples/navigation-menu/overflow.tsx
examples/navigation-menu/overflow.tsx
"use client";

import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuSection,
  NavigationMenuTrigger,
} from "@dethink/components";

export function NavigationMenuOverflow() {
  return (
    <div className="min-h-[16rem]">
      <NavigationMenu aria-label="Product">
        <NavigationMenuList>
          <NavigationMenuItem>
            <NavigationMenuLink current href="#overview">
              Overview
            </NavigationMenuLink>
          </NavigationMenuItem>
          <NavigationMenuItem>
            <NavigationMenuLink href="#projects">Projects</NavigationMenuLink>
          </NavigationMenuItem>
          {/* Secondary destinations stay reachable on narrow screens by
              collapsing behind a disclosure trigger instead of wrapping. */}
          <NavigationMenuItem className="lg:hidden" value="more">
            <NavigationMenuTrigger>More</NavigationMenuTrigger>
            <NavigationMenuContent>
              <NavigationMenuSection>
                <NavigationMenuLink href="#reports">Reports</NavigationMenuLink>
                <NavigationMenuLink href="#audit">Audit log</NavigationMenuLink>
                <NavigationMenuLink href="#settings">
                  Settings
                </NavigationMenuLink>
              </NavigationMenuSection>
            </NavigationMenuContent>
          </NavigationMenuItem>
          {/* On wide screens the same links render inline. */}
          <NavigationMenuItem className="max-lg:hidden">
            <NavigationMenuLink href="#reports">Reports</NavigationMenuLink>
          </NavigationMenuItem>
          <NavigationMenuItem className="max-lg:hidden">
            <NavigationMenuLink href="#audit">Audit log</NavigationMenuLink>
          </NavigationMenuItem>
          <NavigationMenuItem className="max-lg:hidden">
            <NavigationMenuLink href="#settings">Settings</NavigationMenuLink>
          </NavigationMenuItem>
        </NavigationMenuList>
      </NavigationMenu>
    </div>
  );
}
NavigationMenu anatomy
PropWhat it doesDefault
variant / size / orientation"default" | "quiet" | "underline" / "sm" | "md" | "lg" / "horizontal" | "vertical"Token-backed presentation of the whole menu; links and triggers inherit these through context."default" / "md" / "horizontal"
value / defaultValue / onValueChangestring | null / string | null / (value) => voidControlled or uncontrolled open flyout item, keyed by NavigationMenuItem value.Not set
activationMode"click" | "hover" | "focus" | "manual"How triggers open panels. Hover adds an intent delay and keeps click/keyboard activation working; manual leaves all state changes to the consumer."click"
delay / closeDelaynumber / numberHover-intent timings in milliseconds for hover activation.150 / 300
motion"none" | "subtle" | "standard" | "expressive"CSS motion preset for panel transitions, directional slides, and staggered reveal. All movement respects prefers-reduced-motion."standard"
NavigationMenuLink โ€” currentboolean | "page" | "location"Marks the current destination with aria-current and a stable data-current attribute.Not set
NavigationMenuLink โ€” disabled / external / icon / asChildboolean / boolean / ReactNode / booleanDisabled links drop their href and expose aria-disabled; external links get safe rel handling; asChild composes router links.Not set
NavigationMenuItem โ€” valuestringStable identity for controlled state, indicator mapping, and directional transitions.auto
NavigationMenuTriggerbutton (disclosure semantics)Native button exposing aria-expanded/aria-controls; never role=menu. showChevron hides the built-in caret.Not set
NavigationMenuViewport / NavigationMenuIndicatoroptional anatomyShared morphing panel host and animated active-item marker; both are optional layers over the inline flyout behavior.Not set