Navigation Menu
Primary site navigation with optional dropdown panels.
@garn/ui/navigation-menuDefault
A trigger with a link panel plus a plain top-level link.
Installation
garn is copy-in — the garn CLI writes this component's source into your project, so you own and can edit it. It resolves any base files and installs the npm dependencies below for you.
npx garn-ui add navigation-menu- Registry
navigation-menu- Source
- navigation-menu.tsx
- Deps
@radix-ui/react-navigation-menuclass-variance-authoritylucide-react- Registry deps
utils
Import
import { NavigationMenu } from "@garn/ui/navigation-menu";Props
Generated from the component's TypeScript types.
No component-specific props — this is a thin wrapper over its native element.
Styling
Target these data-slots and remap these tokens to restyle without forking the component.
[data-slot="navigation-menu"]| Property | Token | Tier |
|---|---|---|
triggerHeight | --garn-control-h-md | semantic · air |
listGap | --garn-gap-inline | semantic · air |
motion | --garn-motion-base | semantic |
Overview
NavigationMenu is primary site navigation with optional rich dropdown panels — a top header nav or mega-menu. NavigationMenu owns which item is open and hosts a shared Viewport; each NavigationMenuItem is either a direct link or a NavigationMenuTrigger + NavigationMenuContent panel for grouped destinations. It's for navigating to places; for menus of actions use DropdownMenu/Menubar, and for in-page section switching use Tabs.
Guidelines
Use it to navigate, not to run actions. Its items lead to pages/sections; commands belong in a DropdownMenu or Menubar. Keep the top level short and label items by destination, not feature jargon.
Keep dropdown/mega panels scannable. When an item expands a panel, group links under clear headings and keep the panel shallow — a wall of links is as hard to use as no menu. Mark the current section so users know where they are.
Make every destination reachable by keyboard and on mobile. Triggers open on focus/Enter and the panel is navigable; don't gate links behind hover-only reveals. Provide a responsive collapse (a Sheet/drawer) so the nav still works on small screens.
Best practices
- Use NavigationMenuLink (asChild) for real navigation, and navigationMenuTriggerStyle() so links match triggers.
- Reserve NavigationMenuTrigger/Content for items that actually reveal a panel.
- Mark the current destination with
active; label the nav if the page has more than one.
- Don't use it for in-page tabs or app command bars.
- Don't put a trigger on items that are just links.
- Don't bury primary destinations behind triggers unnecessarily.
Content guidelines
- Use short, destination-named links and keep top-level labels broad and scannable.
- In mega-menu panels, group links under clear category headings.
Accessibility
- Role
navigation- Focus
- Triggers and links show a focus ring; panels animate in the shared Viewport.
Keyboard
| Tab | Move between links and triggers. |
| EnterSpaceArrowDown | Open the focused item's panel. |
| Escape | Close the open panel. |
- • The Root is a <nav> landmark; items are links or disclosure triggers that reveal aria-controlled panels.
- • Use NavigationMenuLink for real navigation (asChild to wrap a router Link); mark the current page with `active`.
- • Only use a trigger for items that reveal a panel — plain destinations are just links.
- Status
- Stable
- Version
v0.3.0- Introduced
v0.1.0
garn doesn't yet record a per-release version history. This reflects the component's current lifecycle state; full changelog entries will appear once the metadata pipeline emits a lifecycle.history field.