// preview in
saved for every page

Navigation menu

The main links of a site, in a `<nav>`, with optional panels that open from a trigger, such as a products mega menu. It takes people to pages; for commands, use a Menu or a Menubar.

Built on Base UIPattern WAI-ARIA Disclosure Navigation MenuClient componentSource ↗

Installation

Set up Camaleo once (Installation), then import the parts you need. Panels render in a portal and keep the skin, mode and brand of the page around them.

import { NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink } from "@camaleo/react";

Anatomy

NavigationMenu renders the <nav>; give it an aria-label. Each NavigationMenuItem holds either a NavigationMenuLink or a NavigationMenuTrigger with its NavigationMenuContent, the panel that opens below it.

Examples

Every example is a real file you can copy. They all wear the skin, mode and brand from the bar above, and every panel starts closed.

minimal · light · #3fa34d

Links only

When every top item is a page, you don't need panels: a bar of NavigationMenuLinks is a plain list of real links, one Tab stop each.

Products panel

Open Products. A short description under each name tells people which product fits before they click, and the icon helps them find it again next time.

Featured card in the panel

Promote one timely page, like next week's webinar, beside the regular links. Make the whole card one link so it stays one Tab stop.

Current page

Click the links. active sets aria-current="page", which screen readers announce as "current page" and the skin underlines, so it isn't shown by color alone.

Hover delay

Move the pointer across the bar. delay and closeDelay stop panels from flashing open when someone is just passing over them on the way to the page.

Vertical

For the sections of one area, like settings, stack the list down the side. orientation="vertical" switches the arrow keys to ↑ and ↓.

Named landmarks

Screen reader users jump between landmarks by name. With two navs on the page, "Main" and "Footer" tell them apart; two unnamed navs both read as "navigation".

The bar wraps rather than collapses: it has no phone layout of its own. Below about 640px, swap it for a menu button that opens a Drawer with the same links.

In context

The navigation menu sits in the header of a site or a section. These are whole pieces of UI you can copy, in the skin you picked.

Nimbo
Invoices that pay themselvesReminders, card payments and reconciliation in one place.
Product site headerNavigationMenu · Button · Card
Casa Verde
Store departmentsNavigationMenu · SearchInput · IconButton · Badge
Invoicing

Set up recurring invoices

Updated Oct 3, 2026 · 4 min read

Pick a client, choose how often to bill them and Nimbo sends each invoice on the same day every month.
Help center articleNavigationMenu · Card · Badge

Guidelines

DoName places people go.

"Invoices", "Clients", "Reports": each label is a page, so people know where they'll land and can open it in a new tab.

Don’tCommands dressed as links.

"Export CSV" and "Archive" don't take you anywhere. Put actions in a Menu or a Menubar, where they are announced as commands.

DoA few links, each with a line of help.

Three options with a sentence each are faster to choose from than a list of names people have to guess at.

Don’tEvery page in one panel.

Twelve links with no groups or descriptions turn the panel into a sitemap. Split them by topic, or link to a page that lists them.

Props

PropTypeDefaultDescription
sideOffsetnumber8Gap between a trigger and its panel, in pixels.
align"center" | "end" | "start""start"How the panel lines up with its trigger.
valueanynullThe value of the item whose panel is open, for a controlled menu. null closes it.
defaultValueanynullThe item whose panel starts open. Leave it empty: nothing should open by itself.
onValueChange(value, eventDetails) => void—Called when a panel opens or closes, with the reason in eventDetails.
delaynumber50How long the pointer must rest on a trigger before its panel opens, in milliseconds.
closeDelaynumber50How long a panel waits before closing after the pointer leaves, in milliseconds.
orientation"horizontal" | "vertical"'horizontal'Which arrow keys move between the top items: ← → or ↑ ↓.

These are the props of NavigationMenu. NavigationMenuLink takes active (sets aria-current="page") and closeOnClick. NavigationMenuTrigger takes hideIcon, and NavigationMenuContent takes align and sideOffset. Give NavigationMenuItem a value when you control the menu.

Styling hooks

Restyle it without forking: target the attributes, or set the tokens on a parent, a skin or the nav itself.

Attributes

data-popup-openon the trigger whose panel is open
aria-current · data-activepage · on the link to the current page
data-openon the open panel
data-side · data-alignwhere the panel sits next to its trigger

Tokens it reads

Color

--cml-accent--cml-border-control--cml-fg--cml-fg-secondary--cml-focus-offset--cml-focus-ring--cml-focus-width--cml-popover-bg--cml-popover-border--cml-shadow-popover--cml-surface-raised

Shape & size

--cml-border-width--cml-popover-border-width--cml-radius-control--cml-radius-popover

Type & motion

--cml-font-body--cml-motion-duration

This component only

--cml-item-hover--cml-nav-item-height--cml-nav-item-radius--cml-nav-popup-radius--cml-nav-trigger-open-bg

Accessibility

Tab / Shift + TabMoves between the top links and triggers. Each one is its own Tab stop, like any list of links.
→ / ←Also moves between the top items (↓ / ↑ with orientation="vertical"). It doesn't switch the open panel.
Enter / SpaceOn a trigger: opens or closes its panel. On a link: follows it.
↓On a trigger in a horizontal bar: opens its panel.
EscCloses the panel and returns focus to its trigger.
Was this page helpful? · Edit this page on GitHub