Skip to main content

Navigation Menu

Composable navigation menu primitive with trigger/content/viewport parts.

import * as NavigationMenu from '@gentleduck/primitives/navigation-menu'
import * as NavigationMenu from '@gentleduck/primitives/navigation-menu'

Usage

<NavigationMenu.Root>
  <NavigationMenu.List>
    <NavigationMenu.Item value="docs">
      <NavigationMenu.Trigger>Docs</NavigationMenu.Trigger>
      <NavigationMenu.Content>
        <NavigationMenu.Link href="/docs/getting-started">Getting Started</NavigationMenu.Link>
      </NavigationMenu.Content>
    </NavigationMenu.Item>
  </NavigationMenu.List>
  <NavigationMenu.Indicator />
  <NavigationMenu.Viewport />
</NavigationMenu.Root>
<NavigationMenu.Root>
  <NavigationMenu.List>
    <NavigationMenu.Item value="docs">
      <NavigationMenu.Trigger>Docs</NavigationMenu.Trigger>
      <NavigationMenu.Content>
        <NavigationMenu.Link href="/docs/getting-started">Getting Started</NavigationMenu.Link>
      </NavigationMenu.Content>
    </NavigationMenu.Item>
  </NavigationMenu.List>
  <NavigationMenu.Indicator />
  <NavigationMenu.Viewport />
</NavigationMenu.Root>

API

PropTypeDefaultDescription
valuestring--Controlled open item value
defaultValuestring''Initial open item value
onValueChange(value: string) => void--Called when open value changes
dir'ltr' | 'rtl'--Text direction. Resolved with useDirection (dir prop -> DirectionProvider -> 'ltr').
orientation'horizontal' | 'vertical''horizontal'Menu orientation
delayDurationnumber200Delay before opening item on pointer move
skipDelayDurationnumber300Time window to skip reopen delay
...propsReact.ComponentPropsWithoutRef<'nav'>--Additional props for root nav
PropTypeDefaultDescription
valuestring--Controlled sub-menu value
defaultValuestring''Initial sub-menu value
onValueChange(value: string) => void--Called when sub-menu value changes
orientation'horizontal' | 'vertical''horizontal'Sub-menu orientation

List wrapper for menu items and indicator tracking.

PropTypeDefaultDescription
valuestringauto-generatedStable item key used by trigger/content pairing

Interactive trigger button for an item. Sets aria-expanded, aria-controls, and data-state automatically.

Content panel for an item. Supports pointer/focus outside handlers from dismissable layer props.

PropTypeDefaultDescription
forceMounttrue--Keep mounted for animation control

Composable link slot used inside content.

PropTypeDefaultDescription
activebooleanfalseMarks link as current page (aria-current="page")
onSelect(event: Event) => void--Called on link selection before root dismiss

Positions an active-item indicator relative to the current trigger.

PropTypeDefaultDescription
forceMounttrue--Keep mounted for animation control

Shared animated viewport that hosts active content.

PropTypeDefaultDescription
forceMounttrue--Keep viewport mounted for animation control

Scope

import { createNavigationMenuScope } from '@gentleduck/primitives/navigation-menu'
import { createNavigationMenuScope } from '@gentleduck/primitives/navigation-menu'

createNavigationMenuScope is exported for advanced composition and nested-scoped integration.