# Navigation Menu

A site navigation bar whose items open popover or full-width panels of links.

Navigation Menu is an open-source component from suiss/ui for React. The @esuiss/ui CLI copies its source into your project, so you own the code.

Source: https://ui.suiss.app/docs/components/navigation-menu

**React**

**Example**

```tsx
import {
  BookOpenIcon,
  ChartLineIcon,
  CodeIcon,
  LifebuoyIcon,
  LightningIcon,
  ShieldCheckIcon,
} from "@phosphor-icons/react"
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
  navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu"

const products = [
  {
    title: "Analytics",
    description: "Track traffic and conversions in real time.",
    icon: (
      <ChartLineIcon className="mt-0.5" />
    ),
  },
  {
    title: "Automations",
    description: "Run workflows when events happen.",
    icon: (
      <LightningIcon className="mt-0.5" />
    ),
  },
  {
    title: "Security",
    description: "Single sign-on, audit logs, and roles.",
    icon: (
      <ShieldCheckIcon className="mt-0.5" />
    ),
  },
]

const resources = [
  {
    title: "Documentation",
    icon: (
      <BookOpenIcon />
    ),
  },
  {
    title: "API reference",
    icon: (
      <CodeIcon />
    ),
  },
  {
    title: "Help center",
    icon: (
      <LifebuoyIcon />
    ),
  },
]

export default function NavigationMenuDemo() {
  return (
    <div className="flex min-h-96 items-start justify-center">
      <NavigationMenu align="start">
        <NavigationMenuList>
          <NavigationMenuItem value="products">
            <NavigationMenuTrigger>Products</NavigationMenuTrigger>
            <NavigationMenuContent>
              <ul className="grid w-96 gap-1">
                {products.map((product) => (
                  <li key={product.title}>
                    <NavigationMenuLink href="#" className="items-start gap-3">
                      {product.icon}
                      <div className="flex flex-col gap-1">
                        <span className="font-medium">{product.title}</span>
                        <span className="text-muted-foreground">
                          {product.description}
                        </span>
                      </div>
                    </NavigationMenuLink>
                  </li>
                ))}
              </ul>
            </NavigationMenuContent>
          </NavigationMenuItem>
          <NavigationMenuItem value="resources">
            <NavigationMenuTrigger>Resources</NavigationMenuTrigger>
            <NavigationMenuContent>
              <ul className="grid w-56 gap-1">
                {resources.map((resource) => (
                  <li key={resource.title}>
                    <NavigationMenuLink href="#">
                      {resource.icon}
                      {resource.title}
                    </NavigationMenuLink>
                  </li>
                ))}
              </ul>
            </NavigationMenuContent>
          </NavigationMenuItem>
          <NavigationMenuItem>
            <NavigationMenuLink
              href="#"
              className={navigationMenuTriggerStyle()}
            >
              Pricing
            </NavigationMenuLink>
          </NavigationMenuItem>
        </NavigationMenuList>
      </NavigationMenu>
    </div>
  )
}
```

Navigation Menu wraps the navigation menu primitive of the chosen base. `NavigationMenu` is the root; inside it, `NavigationMenuList` holds `NavigationMenuItem` entries. An item contains either a `NavigationMenuTrigger` with `NavigationMenuContent`, or a single `NavigationMenuLink`. Inside content, use `NavigationMenuLabel` for column headings and `NavigationMenuLink` for destinations.

The root renders the popup for you. With `layout="popover"` it adds a `NavigationMenuPositioner`, a floating card that resizes and slides between items. With `layout="panel"` it adds a `NavigationMenuPanel`, a full-width sheet under the bar with a blurred backdrop, like a store's global navigation. Use Navigation Menu for site navigation links; use Menubar or Dropdown Menu for commands.

## Installation

### CLI

```bash title="Terminal"
npx shadcn@latest add @esuiss/navigation-menu
```

Works in any project with a `components.json`. See [Installation](https://ui.suiss.app/docs/installation#add-components) for the one-line registry setup. Or use the suiss/ui CLI:

```bash title="Terminal"
npx @esuiss/ui@latest add navigation-menu
```

### Manual

1. Install the dependencies and add the [`cn` helper](https://ui.suiss.app/docs/installation#the-cn-helper):

```bash title="Terminal"
npm install @base-ui/react @phosphor-icons/react class-variance-authority
```

2. Copy the source into `components/ui/navigation-menu.tsx`:

```tsx title="components/ui/navigation-menu.tsx"
"use client"

import { NavigationMenu as NavigationMenuPrimitive } from "@base-ui/react/navigation-menu"
import { CaretDownIcon } from "@phosphor-icons/react"
import { cva } from "class-variance-authority"
import { cn } from "@/lib/utils"

function NavigationMenu({
  align = "start",
  layout = "popover",
  anchor,
  className,
  children,
  ...props
}: NavigationMenuPrimitive.Root.Props &
  Pick<NavigationMenuPrimitive.Positioner.Props, "align" | "anchor"> & {
    layout?: "popover" | "panel"
  }) {
  return (
    <NavigationMenuPrimitive.Root
      data-slot="navigation-menu"
      data-layout={layout}
      className={cn(
        "group/navigation-menu relative flex max-w-max flex-1 items-center justify-center",
        className
      )}
      {...props}
    >
      {children}
      {layout === "panel" ? (
        <NavigationMenuPanel anchor={anchor} />
      ) : (
        <NavigationMenuPositioner align={align} anchor={anchor} />
      )}
    </NavigationMenuPrimitive.Root>
  )
}

function NavigationMenuList({
  className,
  ...props
}: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.List>) {
  return (
    <NavigationMenuPrimitive.List
      data-slot="navigation-menu-list"
      className={cn(
        "group flex flex-1 list-none items-center justify-center gap-0",
        className
      )}
      {...props}
    />
  )
}

function NavigationMenuItem({
  className,
  ...props
}: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.Item>) {
  return (
    <NavigationMenuPrimitive.Item
      data-slot="navigation-menu-item"
      className={cn("relative", className)}
      {...props}
    />
  )
}

const navigationMenuTriggerStyle = cva(
  "group/navigation-menu-trigger inline-flex h-9 w-max items-center justify-center rounded-md px-4.5 py-2.5 text-sm transition-colors outline-none hover:bg-accent focus:bg-accent focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none data-popup-open:bg-accent data-popup-open:hover:bg-accent group-data-[layout=panel]/navigation-menu:h-11 group-data-[layout=panel]/navigation-menu:rounded-none group-data-[layout=panel]/navigation-menu:bg-transparent group-data-[layout=panel]/navigation-menu:px-2.5 group-data-[layout=panel]/navigation-menu:text-xs group-data-[layout=panel]/navigation-menu:text-foreground/80 group-data-[layout=panel]/navigation-menu:transition-[color] group-data-[layout=panel]/navigation-menu:duration-300 group-data-[layout=panel]/navigation-menu:hover:bg-transparent group-data-[layout=panel]/navigation-menu:hover:text-accent-foreground group-data-[layout=panel]/navigation-menu:focus:bg-transparent group-data-[layout=panel]/navigation-menu:data-popup-open:bg-transparent group-data-[layout=panel]/navigation-menu:data-popup-open:text-accent-foreground group-data-[layout=panel]/navigation-menu:data-popup-open:hover:bg-transparent group-data-[layout=panel]/navigation-menu:focus-visible:bg-transparent focus:text-accent-foreground disabled:opacity-50"
)

function NavigationMenuTrigger({
  className,
  children,
  ...props
}: NavigationMenuPrimitive.Trigger.Props) {
  return (
    <NavigationMenuPrimitive.Trigger
      data-slot="navigation-menu-trigger"
      className={cn(navigationMenuTriggerStyle(), "group", className)}
      {...props}
    >
      {children}{" "}
      <CaretDownIcon
        className="relative top-px ms-1 size-3 transition duration-300 group-data-popup-open/navigation-menu-trigger:rotate-180 group-data-[layout=panel]/navigation-menu:hidden"
        aria-hidden="true"
      />
    </NavigationMenuPrimitive.Trigger>
  )
}

function NavigationMenuContent({
  className,
  ...props
}: NavigationMenuPrimitive.Content.Props) {
  return (
    <NavigationMenuPrimitive.Content
      data-slot="navigation-menu-content"
      className={cn(
        "data-ending-style:data-[activation-direction=left]:translate-x-[50%] data-ending-style:data-[activation-direction=right]:translate-x-[-50%] data-starting-style:data-[activation-direction=left]:translate-x-[-50%] data-starting-style:data-[activation-direction=right]:translate-x-[50%] h-full w-auto p-2.5 pe-3 transition-[opacity,transform,translate] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] data-ending-style:opacity-0 data-starting-style:opacity-0 in-data-[slot=navigation-menu-panel]:w-full in-data-[slot=navigation-menu-panel]:translate-x-0! in-data-[slot=navigation-menu-panel]:p-0 in-data-[slot=navigation-menu-panel]:duration-300 in-data-[slot=navigation-menu-panel]:ease-[cubic-bezier(0.4,0,0.6,1)] in-data-[slot=navigation-menu-panel]:data-ending-style:duration-150 in-data-[slot=navigation-menu-panel]:[&_li]:animate-in in-data-[slot=navigation-menu-panel]:[&_li]:fade-in-0 in-data-[slot=navigation-menu-panel]:[&_li]:slide-in-from-top-2 in-data-[slot=navigation-menu-panel]:[&_li]:fill-mode-both in-data-[slot=navigation-menu-panel]:[&_li]:duration-300 in-data-[slot=navigation-menu-panel]:[&_li]:ease-[cubic-bezier(0.4,0,0.6,1)] in-data-[slot=navigation-menu-panel]:[&_li:nth-child(2)]:delay-[25ms] in-data-[slot=navigation-menu-panel]:[&_li:nth-child(3)]:delay-[50ms] in-data-[slot=navigation-menu-panel]:[&_li:nth-child(4)]:delay-75 in-data-[slot=navigation-menu-panel]:[&_li:nth-child(5)]:delay-100 in-data-[slot=navigation-menu-panel]:[&_li:nth-child(6)]:delay-[125ms] in-data-[slot=navigation-menu-panel]:[&_li:nth-child(n+7)]:delay-150 motion-reduce:[&_li]:animate-none",
        className
      )}
      {...props}
    />
  )
}

function NavigationMenuPositioner({
  className,
  side = "bottom",
  sideOffset = 8,
  align = "start",
  alignOffset = 0,
  ...props
}: NavigationMenuPrimitive.Positioner.Props) {
  return (
    <NavigationMenuPrimitive.Portal>
      <NavigationMenuPrimitive.Positioner
        data-slot="navigation-menu-positioner"
        side={side}
        sideOffset={sideOffset}
        align={align}
        alignOffset={alignOffset}
        className={cn(
          "isolate z-50 h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] data-instant:transition-none data-[side=bottom]:before:absolute data-[side=bottom]:before:-top-2.5 data-[side=bottom]:before:inset-e-0 data-[side=bottom]:before:inset-s-0 data-[side=bottom]:before:h-2.5",
          className
        )}
        {...props}
      >
        <NavigationMenuPrimitive.Popup
          data-slot="navigation-menu-popup"
          className="relative h-(--popup-height) w-(--popup-width) origin-(--transform-origin) rounded-2xl bg-popover text-popover-foreground shadow-lg ring-1 ring-foreground/5 transition-[opacity,transform,width,height,scale,translate] duration-[0.35s] ease-[cubic-bezier(0.22,1,0.36,1)] outline-none data-ending-style:scale-90 data-ending-style:opacity-0 data-ending-style:duration-150 data-starting-style:scale-90 data-starting-style:opacity-0 dark:ring-foreground/10"
        >
          <NavigationMenuPrimitive.Viewport className="relative size-full overflow-hidden" />
        </NavigationMenuPrimitive.Popup>
      </NavigationMenuPrimitive.Positioner>
    </NavigationMenuPrimitive.Portal>
  )
}

function NavigationMenuPanel({
  className,
  anchor,
  ...props
}: NavigationMenuPrimitive.Positioner.Props) {
  return (
    <NavigationMenuPrimitive.Portal>
      <NavigationMenuPrimitive.Backdrop
        data-slot="navigation-menu-backdrop"
        className="fixed inset-0 z-40 bg-black/20 backdrop-blur-lg transition-opacity duration-350 ease-[cubic-bezier(0.45,0,0.2,1)] data-ending-style:opacity-0 data-starting-style:opacity-0 motion-reduce:transition-none"
      />
      <NavigationMenuPrimitive.Positioner
        anchor={anchor}
        side="bottom"
        align="start"
        sideOffset={0}
        collisionPadding={0}
        className={cn(
          "isolate z-50 h-(--positioner-height) w-(--anchor-width)",
          className
        )}
        {...props}
      >
        <NavigationMenuPrimitive.Popup
          data-slot="navigation-menu-panel"
          className="relative h-(--popup-height) w-full overflow-hidden bg-background text-foreground transition-[height] dark:bg-muted duration-450 ease-[cubic-bezier(0.45,0,0.2,1)] outline-none data-ending-style:h-0 data-ending-style:duration-300 data-starting-style:h-0 motion-reduce:transition-none"
        >
          <NavigationMenuPrimitive.Viewport className="relative size-full" />
        </NavigationMenuPrimitive.Popup>
      </NavigationMenuPrimitive.Positioner>
    </NavigationMenuPrimitive.Portal>
  )
}

function NavigationMenuLink({
  className,
  size = "default",
  ...props
}: NavigationMenuPrimitive.Link.Props & {
  size?: "default" | "lg"
}) {
  return (
    <NavigationMenuPrimitive.Link
      data-slot="navigation-menu-link"
      data-size={size}
      className={cn(
        "flex items-center gap-1.5 rounded-md p-3 text-sm transition-colors outline-none hover:bg-accent focus:bg-accent focus-visible:ring-3 focus-visible:ring-ring/50 in-data-[slot=navigation-menu-content]:rounded-md data-active:bg-accent data-active:hover:bg-accent data-active:focus:bg-accent data-[size=lg]:text-2xl data-[size=lg]:font-semibold [&_svg:not([class*='size-'])]:size-4 hover:text-accent-foreground focus:text-accent-foreground",
        "in-data-[slot=navigation-menu-panel]:w-fit in-data-[slot=navigation-menu-panel]:rounded-sm in-data-[slot=navigation-menu-panel]:bg-transparent in-data-[slot=navigation-menu-panel]:px-0 in-data-[slot=navigation-menu-panel]:py-1 in-data-[slot=navigation-menu-panel]:text-xs in-data-[slot=navigation-menu-panel]:font-semibold in-data-[slot=navigation-menu-panel]:text-foreground in-data-[slot=navigation-menu-panel]:hover:bg-transparent in-data-[slot=navigation-menu-panel]:hover:text-primary in-data-[slot=navigation-menu-panel]:focus:bg-transparent in-data-[slot=navigation-menu-panel]:data-active:bg-transparent in-data-[slot=navigation-menu-panel]:data-[size=lg]:py-0.5 in-data-[slot=navigation-menu-panel]:data-[size=lg]:text-2xl",
        className
      )}
      {...props}
    />
  )
}

function NavigationMenuLabel({
  className,
  ...props
}: React.ComponentProps<"p">) {
  return (
    <p
      data-slot="navigation-menu-label"
      className={cn("pb-2 text-xs text-muted-foreground", className)}
      {...props}
    />
  )
}

function NavigationMenuIndicator({
  className,
  ...props
}: React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.Icon>) {
  return (
    <NavigationMenuPrimitive.Icon
      data-slot="navigation-menu-indicator"
      className={cn(
        "top-full z-1 flex h-1.5 items-end justify-center overflow-hidden opacity-0 transition-opacity data-popup-open:opacity-100",
        className
      )}
      {...props}
    >
      <div className="relative top-[60%] h-2 w-2 rotate-45 rounded-ss-sm bg-border shadow-md" />
    </NavigationMenuPrimitive.Icon>
  )
}

export {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuIndicator,
  NavigationMenuItem,
  NavigationMenuLabel,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuPanel,
  NavigationMenuPositioner,
  NavigationMenuTrigger,
  navigationMenuTriggerStyle,
}
```

3. Update the import paths to match your project.

## Usage

```tsx
import { NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuPositioner, NavigationMenuPanel, NavigationMenuLink, NavigationMenuLabel, NavigationMenuIndicator } from "@/components/ui/navigation-menu"
```

```tsx
<div className="flex min-h-96 items-start justify-center">
  <NavigationMenu align="start">
    <NavigationMenuList>
      <NavigationMenuItem value="products">
        <NavigationMenuTrigger>Products</NavigationMenuTrigger>
        <NavigationMenuContent>
          <ul className="grid w-96 gap-1">
            {products.map((product) => (
              <li key={product.title}>
                <NavigationMenuLink href="#" className="items-start gap-3">
                  <product.icon className="mt-0.5" />
                  <div className="flex flex-col gap-1">
                    <span className="font-medium">{product.title}</span>
                    <span className="text-muted-foreground">
                      {product.description}
                    </span>
                  </div>
                </NavigationMenuLink>
              </li>
            ))}
          </ul>
        </NavigationMenuContent>
      </NavigationMenuItem>
      <NavigationMenuItem value="resources">
        <NavigationMenuTrigger>Resources</NavigationMenuTrigger>
        <NavigationMenuContent>
          <ul className="grid w-56 gap-1">
            {resources.map((resource) => (
              <li key={resource.title}>
                <NavigationMenuLink href="#">
                  <resource.icon />
                  {resource.title}
                </NavigationMenuLink>
              </li>
            ))}
          </ul>
        </NavigationMenuContent>
      </NavigationMenuItem>
      <NavigationMenuItem>
        <NavigationMenuLink href="#" className={navigationMenuTriggerStyle()}>
          Pricing
        </NavigationMenuLink>
      </NavigationMenuItem>
    </NavigationMenuList>
  </NavigationMenu>
</div>
```

Give each item with content a `value` so the menu can be opened by default or controlled with `value`, `defaultValue` and `onValueChange` on the root. The root also accepts `align` for the popover and `anchor` for either layout; in `panel` layout, pass a ref to the full-width bar as `anchor` so the panel spans its width.

To style a top-level link like a trigger, pass `navigationMenuTriggerStyle()` as its `className`. Set `active` on a link to mark the current page.

## Examples

### By default

A menu that opens the Products item on mount with `defaultValue`.

**Example**

```tsx
import {
  BookOpenIcon,
  ChartLineIcon,
  CodeIcon,
  LifebuoyIcon,
  LightningIcon,
  ShieldCheckIcon,
} from "@phosphor-icons/react"
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
  navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu"

const products = [
  {
    title: "Analytics",
    description: "Track traffic and conversions in real time.",
    icon: (
      <ChartLineIcon className="mt-0.5" />
    ),
  },
  {
    title: "Automations",
    description: "Run workflows when events happen.",
    icon: (
      <LightningIcon className="mt-0.5" />
    ),
  },
  {
    title: "Security",
    description: "Single sign-on, audit logs, and roles.",
    icon: (
      <ShieldCheckIcon className="mt-0.5" />
    ),
  },
]

const resources = [
  {
    title: "Documentation",
    icon: (
      <BookOpenIcon />
    ),
  },
  {
    title: "API reference",
    icon: (
      <CodeIcon />
    ),
  },
  {
    title: "Help center",
    icon: (
      <LifebuoyIcon />
    ),
  },
]

export default function NavigationMenuOpenByDefault() {
  return (
    <div className="flex min-h-96 items-start justify-center">
      <NavigationMenu align="start" defaultValue="products">
        <NavigationMenuList>
          <NavigationMenuItem value="products">
            <NavigationMenuTrigger>Products</NavigationMenuTrigger>
            <NavigationMenuContent>
              <ul className="grid w-96 gap-1">
                {products.map((product) => (
                  <li key={product.title}>
                    <NavigationMenuLink href="#" className="items-start gap-3">
                      {product.icon}
                      <div className="flex flex-col gap-1">
                        <span className="font-medium">{product.title}</span>
                        <span className="text-muted-foreground">
                          {product.description}
                        </span>
                      </div>
                    </NavigationMenuLink>
                  </li>
                ))}
              </ul>
            </NavigationMenuContent>
          </NavigationMenuItem>
          <NavigationMenuItem value="resources">
            <NavigationMenuTrigger>Resources</NavigationMenuTrigger>
            <NavigationMenuContent>
              <ul className="grid w-56 gap-1">
                {resources.map((resource) => (
                  <li key={resource.title}>
                    <NavigationMenuLink href="#">
                      {resource.icon}
                      {resource.title}
                    </NavigationMenuLink>
                  </li>
                ))}
              </ul>
            </NavigationMenuContent>
          </NavigationMenuItem>
          <NavigationMenuItem>
            <NavigationMenuLink
              href="#"
              className={navigationMenuTriggerStyle()}
            >
              Pricing
            </NavigationMenuLink>
          </NavigationMenuItem>
        </NavigationMenuList>
      </NavigationMenu>
    </div>
  )
}
```

### Links only

A bar of plain links styled like triggers, with the first marked `active`.

**Example**

```tsx
import {
  NavigationMenu,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu"

export default function NavigationMenuLinksOnly() {
  return (
    <div className="flex min-h-96 items-start justify-center">
      <NavigationMenu align="start">
        <NavigationMenuList>
          {["Overview", "Customers", "Changelog", "Blog"].map(
            (label, index) => (
              <NavigationMenuItem key={label}>
                <NavigationMenuLink
                  href="#"
                  active={index === 0}
                  className={navigationMenuTriggerStyle()}
                >
                  {label}
                </NavigationMenuLink>
              </NavigationMenuItem>
            )
          )}
        </NavigationMenuList>
      </NavigationMenu>
    </div>
  )
}
```

### Panel

The `panel` layout anchored to a sticky header, with columns of labelled links and large primary links.

**Example**

```tsx
import * as React from "react"
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLabel,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
  navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu"

const panelMenus = [
  {
    value: "pos",
    label: "POS",
    explore: ["Terminals", "Handhelds", "Compare models"],
    shop: ["Shop POS", "Accessories", "Financing", "Trade in"],
    more: ["POS support", "Setup guide", "Integrations"],
  },
  {
    value: "kitchen",
    label: "Kitchen",
    explore: ["Displays", "Printers"],
    shop: ["Shop Kitchen", "Mounts", "Cables"],
    more: ["Kitchen support", "Station layouts"],
  },
  {
    value: "reservations",
    label: "Reservations",
    explore: ["Floor plans", "Waitlist", "Guest profiles", "Online booking"],
    shop: ["Plans", "Add-ons"],
    more: ["Reservations support", "Booking widget", "Calendar sync"],
  },
  {
    value: "analytics",
    label: "Analytics",
    explore: ["Reports", "Forecasts"],
    shop: ["Plans", "Data exports"],
    more: ["Analytics support"],
  },
]

function PanelColumn({
  label,
  links,
  size,
}: {
  label: string
  links: string[]
  size?: "default" | "lg"
}) {
  return (
    <div className="flex flex-col">
      <NavigationMenuLabel>{label}</NavigationMenuLabel>
      <ul className="flex flex-col gap-1.5">
        {links.map((link) => (
          <li key={link}>
            <NavigationMenuLink href="#" size={size}>
              {link}
            </NavigationMenuLink>
          </li>
        ))}
      </ul>
    </div>
  )
}

function PanelExample() {
  const ref = React.useRef<HTMLDivElement>(null)

  return (
    <div className="w-full">
      <div
        ref={ref}
        className="sticky top-0 z-50 flex w-full justify-center bg-background/80 backdrop-blur-xl transition-colors duration-300 has-data-popup-open:bg-background dark:bg-muted/80 dark:has-data-popup-open:bg-muted"
      >
        <NavigationMenu layout="panel" anchor={ref}>
          <NavigationMenuList>
            <NavigationMenuItem>
              <NavigationMenuLink
                href="#"
                className={navigationMenuTriggerStyle()}
              >
                Store
              </NavigationMenuLink>
            </NavigationMenuItem>
            {panelMenus.map((menu) => (
              <NavigationMenuItem key={menu.value} value={menu.value}>
                <NavigationMenuTrigger>{menu.label}</NavigationMenuTrigger>
                <NavigationMenuContent>
                  <div className="mx-auto flex max-w-245 gap-16 px-6 pt-10 pb-16">
                    <PanelColumn
                      label={`Explore ${menu.label}`}
                      links={menu.explore}
                      size="lg"
                    />
                    <PanelColumn
                      label={`Shop ${menu.label}`}
                      links={menu.shop}
                    />
                    <PanelColumn
                      label={`More from ${menu.label}`}
                      links={menu.more}
                    />
                  </div>
                </NavigationMenuContent>
              </NavigationMenuItem>
            ))}
            <NavigationMenuItem>
              <NavigationMenuLink
                href="#"
                className={navigationMenuTriggerStyle()}
              >
                Support
              </NavigationMenuLink>
            </NavigationMenuItem>
          </NavigationMenuList>
        </NavigationMenu>
      </div>
      <div className="mx-auto flex max-w-245 flex-col items-center gap-3 px-6 py-24 text-center">
        <h2 className="text-5xl font-semibold">Hestia POS</h2>
        <p className="text-xl text-muted-foreground">
          Orders, kitchen and tables in one place.
        </p>
        <div className="mt-8 grid w-full grid-cols-3 gap-4">
          {["bg-blue-500", "bg-orange-500", "bg-green-500"].map((tint) => (
            <div key={tint} className={`aspect-4/3 rounded-3xl ${tint}`} />
          ))}
        </div>
      </div>
    </div>
  )
}

export default function NavigationMenuPanel() {
  return (
    <div className="flex min-h-96 items-start justify-center">
      <PanelExample />
    </div>
  )
}
```

## API Reference

- `NavigationMenu`
- `NavigationMenuList`
  - `NavigationMenuItem`
    - `NavigationMenuTrigger`
    - `NavigationMenuContent`
      - `NavigationMenuLink`
    - `NavigationMenuLink`

### NavigationMenu

The root that manages open state and renders the popover or panel popup.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `layout` | `"popover" \| "panel"` | `"popover"` | Chooses the popup style: `popover` for a floating card, or `panel` for a full-width sheet with a backdrop. |

Also accepts the props of the primitive parts it wraps.

### NavigationMenuList

The horizontal list of top-level items.

Also accepts the props of `React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.List>`.

### NavigationMenuItem

One top-level entry, holding a trigger with content or a single link.

Also accepts the props of `React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.Item>`.

### NavigationMenuTrigger

The button that opens its item's content, with a caret in the popover layout.

Also accepts the props of the primitive part it wraps.

### NavigationMenuContent

The content shown in the popup when its item is open.

Also accepts the props of the primitive part it wraps.

### NavigationMenuPositioner

The floating popover card used by the `popover` layout.

Also accepts the props of the primitive part it wraps.

### NavigationMenuPanel

The full-width sheet and backdrop used by the `panel` layout.

Also accepts the props of the primitive part it wraps.

### NavigationMenuLink

A navigation link, either in the bar or inside content.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` | `"default" \| "lg"` | `"default"` | Sets the link size; `lg` uses large, semibold text for primary destinations. |

Also accepts the props of the primitive part it wraps.

### NavigationMenuLabel

A small secondary heading above a group of links.

Also accepts the props of `React.ComponentProps<"p">`.

### NavigationMenuIndicator

A small arrow that fades in while its menu is open.

Also accepts the props of `React.ComponentPropsWithRef<typeof NavigationMenuPrimitive.Icon>`.

## Accessibility

- Triggers are buttons with `aria-expanded` reflecting whether their content is open.
- Enter opens a focused trigger, and Tab moves focus into the open content.
- Escape closes the open content and returns focus to its trigger.
- Hovering another trigger switches the open content.
- A link with `active` set receives `aria-current="page"`.
- The trigger's caret icon is `aria-hidden`.

## Notes

- Styling hooks: `data-slot` values such as `navigation-menu`, `navigation-menu-trigger`, `navigation-menu-content`, `navigation-menu-popup`, `navigation-menu-panel`, `navigation-menu-backdrop` and `navigation-menu-link`. The root exposes `data-layout`; links expose `data-size` and `data-active`.
- Triggers and links restyle themselves automatically in the `panel` layout, and panel list items animate in with a stagger that respects reduced motion.
- `navigationMenuTriggerStyle` is exported for styling links as triggers.
- Uses the `popover`, `background`, `accent` and `primary` colors, with a blurred `bg-black/20` backdrop (`backdrop-blur-lg`).

