Glin UI
Primitive / Moleculebeta

Navigation Menu

Site navigation with animated content panels, links and a shared viewport.

Edit on GitHub

Installation

Install from
pnpm dlx @glinui/cli@latest add navigation-menu

Prefer the package?

Usage

Inline panels

Pass viewport={false} to render each panel under its own trigger instead of a shared viewport.

"use client"
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
navigationMenuTriggerStyle
} from "@glinui/ui"
export function NavInlineExample() {
return (
<div className="mx-auto min-h-56 w-full max-w-xl">
<NavigationMenu aria-label="Docs" viewport={false} defaultValue="learn" className="max-w-none justify-start">
<NavigationMenuList>
<NavigationMenuItem value="learn" className="relative">
<NavigationMenuTrigger>Learn</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="grid w-60 gap-1 p-1">
<li><NavigationMenuLink href="#"><span className="block text-sm font-medium">Quickstart</span><span className="block text-xs text-[var(--color-muted)]">Ship a first page in 5 minutes.</span></NavigationMenuLink></li>
<li><NavigationMenuLink href="#"><span className="block text-sm font-medium">Theming</span><span className="block text-xs text-[var(--color-muted)]">Tokens, modes and variants.</span></NavigationMenuLink></li>
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuLink href="#" className={navigationMenuTriggerStyle()}>Components</NavigationMenuLink>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuLink href="#" className={navigationMenuTriggerStyle()}>Examples</NavigationMenuLink>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
</div>
)
}

Variants

Every look of the shared vocabulary: glinr (the default), plain (shadcn), solid, soft, outline, ghost, gradient and glass. Omit `variant` to follow the ambient design style.

import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger } from "@glinui/ui"
const variants = ["glinr", "plain", "solid", "soft", "outline", "ghost", "gradient", "glass"] as const
export function Demo() {
return (
<div className="grid gap-x-6 gap-y-2 sm:grid-cols-2">
{variants.map((variant) => (
<div key={variant} className="min-h-40">
<NavigationMenu aria-label={`${variant} navigation`} variant={variant}>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>{variant}</NavigationMenuTrigger>
<NavigationMenuContent>
<div className="grid w-48 gap-1">
<NavigationMenuLink href="#">Analytics</NavigationMenuLink>
<NavigationMenuLink href="#">Automation</NavigationMenuLink>
</div>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuLink href="#" active>Docs</NavigationMenuLink>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
</div>
))}
</div>
)
}

Glass (opt-in)

Glass is opt-in and needs a colourful or photographic backdrop. Pick one in the stage header.

import { NavigationMenu, NavigationMenuContent, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, navigationMenuTriggerStyle } from "@glinui/ui"
export function Demo() {
return (
<NavigationMenu aria-label="Main" variant="glass">
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Products</NavigationMenuTrigger>
<NavigationMenuContent>
<div className="grid w-64 gap-1">
<NavigationMenuLink href="#">Analytics</NavigationMenuLink>
<NavigationMenuLink href="#">Automation</NavigationMenuLink>
</div>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuLink href="#" className={navigationMenuTriggerStyle()}>Docs</NavigationMenuLink>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
)
}

Accessibility

  • Rendered as a nav landmark; give it an aria-label.
  • Triggers announce expanded state and control their content.
  • Full roving keyboard support from Radix.

Keyboard Interactions

KeyAction
TabMove to the next trigger or link.
Enter / SpaceOpen the focused trigger.
ArrowLeft / ArrowRightMove between top level items.
ArrowDownEnter open content.
EscapeClose content and return focus to trigger.

ARIA Attributes

  • `aria-expanded` on triggers
  • `aria-controls` links trigger to content
  • `aria-current="page"` on active link

Reduced Motion

Panels fade and scale from 95% on open using transform and opacity only. With prefers-reduced-motion the animation is removed.

Affected properties

opacitytransform

API Reference

PropTypeRequiredDefaultDescription
variantNavigationMenuVariantNoambient style (glinr)Surface of the viewport panel and the trigger pills. Omit it for the ambient design style. `glass` is opt-in and needs a backdrop.
viewportbooleanNotrueRender content in a shared viewport below the list.
delayDurationnumber-200Hover open delay in ms.
dir"ltr" | "rtl"--Reading direction for motion and keyboard.
PropTypeRequiredDefaultDescription
activeboolean--Link: marks the current page with aria-current=page.
navigationMenuTriggerStyle()() => string--Helper to style a plain link like a trigger.
variantNavigationMenuVariantNo-Surface look of the viewport panel and trigger pills. Omit for the ambient design style (glinr by default).
viewportbooleanNotrueRender content in a shared animated viewport (default) or inline per item.

Source

Import directly from the package or browse the source on GitHub. Click any file to view it.

Import

import { NavigationMenu } from "@glinui/ui"

Source Files

Dependencies

@glinui/ui@phosphor-icons/react@radix-ui/react-navigation-menuclass-variance-authority

Generated API Snapshot

Beta

Auto-extracted from TypeScript source in packages/ui/src/components/navigation-menu.tsx. This section is in beta and may lag behind hand-curated docs. Regenerate with pnpm --filter @glinui/docs api:generate.

Generated: 2026-10-08T01:41:21.546Z · Full index: /docs/api-metadata

Primary Props Type

NavigationMenuProps

NavigationMenuProps

PropTypeRequiredDefaultDescription
variantNavigationMenuVariantNo-Surface look of the viewport panel and trigger pills. Omit for the ambient design style (glinr by default).
viewportbooleanNotrueRender content in a shared animated viewport (default) or inline per item.