Skip to content
Tier

Navigation menu

Pro

Site or app navigation with panels that open under their trigger, in Candor's theme (Base UI). Arrow keys move between the triggers and links, Down opens a trigger's panel and moves into it, Escape closes it and returns focus to the trigger. The current page's link is marked aria-current. A link a person can't follow stays, marked and explained.

Markdown
Version 5.2.0· other versions

This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).

Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0 and 2.2.0: the page came later, or had another name then.

Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.

Preview

Loading the preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/navigation-menu

Brings in: layer, locked, motion, tokens, utils · npm: @base-ui/react@^1.9.0, class-variance-authority@^0.7.1, lucide-react@^1.67.0

Usage

TSX · The example above
"use client"

import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
  navigationMenuTriggerStyle,
} from "@/components/candor/ui/navigation-menu"

export default function Example() {
  return (
    <NavigationMenu aria-label="Workspace">
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuTrigger>Reports</NavigationMenuTrigger>
          <NavigationMenuContent>
            <ul className="grid w-72 gap-1">
              <li>
                <NavigationMenuLink href="#weekly" active>
                  <span className="font-medium">Weekly summary</span>
                  <span className="text-xs text-muted-foreground">Runs, failures and spend for the past 7 days.</span>
                </NavigationMenuLink>
              </li>
              <li>
                <NavigationMenuLink href="#audit">
                  <span className="font-medium">Audit trail</span>
                  <span className="text-xs text-muted-foreground">Who changed what, and when.</span>
                </NavigationMenuLink>
              </li>
              <li>
                <NavigationMenuLink href="#export" locked="Exports are off for your workspace.">
                  <span className="font-medium">Scheduled exports</span>
                </NavigationMenuLink>
              </li>
            </ul>
          </NavigationMenuContent>
        </NavigationMenuItem>
        <NavigationMenuItem>
          <NavigationMenuTrigger>Team</NavigationMenuTrigger>
          <NavigationMenuContent>
            <ul className="grid w-60 gap-1">
              <li>
                <NavigationMenuLink href="#members">Members</NavigationMenuLink>
              </li>
              <li>
                <NavigationMenuLink href="#roles">Roles</NavigationMenuLink>
              </li>
            </ul>
          </NavigationMenuContent>
        </NavigationMenuItem>
        <NavigationMenuItem>
          <NavigationMenuLink href="#docs" className={navigationMenuTriggerStyle()}>
            Docs
          </NavigationMenuLink>
        </NavigationMenuItem>
      </NavigationMenuList>
    </NavigationMenu>
  )
}

<NavigationMenu>

PropTypeDefaultDescription
classNamestring | undefined—Classes for the part, merged with Candor's.
styleReact.CSSProperties | undefined—Inline styles for the part, merged over its motion chain.
viewportboolean | undefinedtrueKept from 3.x. On Base UI every panel opens in one shared box under the list that resizes between them, so this only sets `data-viewport` on the menu for the app's own styles.

Also takes the props of Omit<P, "className" | "style">.

<NavigationMenuContent>

The panel a NavigationMenuItem opens beneath the bar.

PropTypeDefaultDescription
classNamestring | undefined—Classes for the part, merged with Candor's.
styleReact.CSSProperties | undefined—Inline styles for the part, merged over its motion chain.

Also takes the props of Omit<P, "className" | "style">.

<NavigationMenuIndicator>

The small arrow under the open panel.

PropTypeDefaultDescription
classNamestring | undefined—Classes for the part, merged with Candor's.
styleReact.CSSProperties | undefined—Inline styles for the part, merged over its motion chain.

Also takes the props of Omit<P, "className" | "style">.

<NavigationMenuItem>

One entry in a NavigationMenuList: a link, or a trigger with its panel.

PropTypeDefaultDescription
classNamestring | undefined—Classes for the part, merged with Candor's.
styleReact.CSSProperties | undefined—Inline styles for the part, merged over its motion chain.

Also takes the props of Omit<P, "className" | "style">.

A link inside a NavigationMenu, styled as one of its entries.

PropTypeDefaultDescription
classNamestring | undefined—Classes for the part, merged with Candor's.
styleReact.CSSProperties | undefined—Inline styles for the part, merged over its motion chain.
lockedstring | null | undefined—Why the link can't be followed right now. When set, it stays focusable and marked `aria-disabled`, following it does nothing, and the reason is shown on hover and focus and read to screen readers (see `Locked`). `null` or left out: unlocked.

Also takes the props of Omit<P, "className" | "style">.

<NavigationMenuList>

The row of entries in a NavigationMenu.

PropTypeDefaultDescription
classNamestring | undefined—Classes for the part, merged with Candor's.
styleReact.CSSProperties | undefined—Inline styles for the part, merged over its motion chain.

Also takes the props of Omit<P, "className" | "style">.

<NavigationMenuTrigger>

The button in a NavigationMenu that opens its panel.

PropTypeDefaultDescription
classNamestring | undefined—Classes for the part, merged with Candor's.
styleReact.CSSProperties | undefined—Inline styles for the part, merged over its motion chain.

Also takes the props of Omit<P, "className" | "style">.

<NavigationMenuViewport>

The box the open panel is drawn in, under the list. NavigationMenu draws it; it is exported for a menu built by hand.

PropTypeDefaultDescription
classNamestring | undefined—Classes for the part, merged with Candor's.
styleReact.CSSProperties | undefined—Inline styles for the part, merged over its motion chain.

Also takes the props of Omit<P, "className" | "style">.

Values

navigationMenuTriggerStyle
(props?: ClassProp | undefined) => string

Motion

MomentFamilyWhat it does
indicatoroverlay, fadeThe small arrow under the open panel fades in when a panel opens and fades out when it closes.
openoverlay, scaleWith the shared viewport (the default), the box under the triggers fades in and scales up a little from the top when a panel opens, and fades out when it closes. Under reduced motion both are a short fade.
slideoverlay, slideWhen the person moves from one open trigger to another, the new panel slides in from the side they moved towards and the old one slides out the same way; with no side to come from it fades. Under reduced motion it is a short fade.
turnreveal, sizeThe chevron beside a trigger turns when its panel opens and turns back when the panel closes. Under reduced motion it turns at once.

Set with --cd-motion-navigation-menu-<moment>-* in your brand file; the families are in the design reference.