Navigation menu Overview

The navigation menu component provides a horizontal or vertical navigation system for web applications. It supports both simple navigation links and complex dropdown content areas with unlimited nesting depth, making it ideal for main navigation bars, mega menus, and hierarchical navigation structures. The component features intelligent hover behavior, keyboard navigation, and automatic active state management.

Mega menus are preferred over multi-level nested menus for better user experience. Mega menus provide all options at once, reducing navigation depth and making it easier for users to find what they're looking for. Use multi-level nesting only when absolutely necessary for complex hierarchical structures.

When to Use

Use navigation menu components when:

  • Creating main site navigation bars
  • Implementing mega menus with rich content
  • Organizing hierarchical navigation structures with multiple levels
  • Building vertical side navigation menus
  • Creating navigation with hover-activated dropdowns

Don't use navigation menu components for:

  • Simple action menus (use command components)
  • Form selection dropdowns (use select or combobox)
  • Contextual actions on content (use command components)
  • Breadcrumb navigation (use breadcrumb component)
Examples Basic Horizontal Navigation

A simple horizontal navigation bar with active state management and clean styling.

<dap-ds-navigation-menu activeHref="/about">
<dap-ds-navigation-menu-item baseHref="/">
  <dap-ds-button slot="trigger" href="/" variant="subtle-menu" >
    <dap-ds-stack direction="row">
      <dap-ds-icon name="home-6-line"></dap-ds-icon>
      Home
    </dap-ds-stack>
  </dap-ds-button>
</dap-ds-navigation-menu-item>

<dap-ds-navigation-menu-item>
  <dap-ds-button slot="trigger" href="/about" variant="subtle-menu" >
    About
  </dap-ds-button>
</dap-ds-navigation-menu-item>

<dap-ds-navigation-menu-item>
  <dap-ds-button slot="trigger" href="/services" variant="subtle-menu" >
    Services
  </dap-ds-button>
</dap-ds-navigation-menu-item>

<dap-ds-navigation-menu-item>
  <dap-ds-button slot="trigger" href="/contact" variant="subtle-menu" >
    Contact
  </dap-ds-button>
</dap-ds-navigation-menu-item>
</dap-ds-navigation-menu>
Navigation with Dropdown Content

Navigation items can contain rich dropdown content for complex menu structures.

<dap-ds-navigation-menu activeHref="/products">
<dap-ds-navigation-menu-item>
  <dap-ds-button slot="trigger" href="/" variant="subtle-menu">
    <dap-ds-stack direction="row">
      <dap-ds-icon name="home-6-line"></dap-ds-icon>
      Home
    </dap-ds-stack>
  </dap-ds-button>
</dap-ds-navigation-menu-item>

<dap-ds-navigation-menu-item baseHref="/products">
  <span slot="title">Products</span>
  
  <dap-ds-stack spacing="100">
    <dap-ds-button href="/web-dev" variant="subtle-menu-item">
      <dap-ds-stack spacing="0">
        <dap-ds-stack direction="row">
          <dap-ds-icon name="tools-line"></dap-ds-icon>
          Web Development
        </dap-ds-stack>
        <dap-ds-typography variant="description">
          Build modern web applications
        </dap-ds-typography>
      </dap-ds-stack>
    </dap-ds-button>

    <dap-ds-button href="/mobile" variant="subtle-menu-item">
      <dap-ds-stack spacing="0">
        <dap-ds-stack direction="row">
          <dap-ds-icon name="cookie-line"></dap-ds-icon>
          Mobile Apps
        </dap-ds-stack>
        <dap-ds-typography variant="description">
          iOS and Android development
        </dap-ds-typography>
      </dap-ds-stack>
    </dap-ds-button>
  </dap-ds-stack>
</dap-ds-navigation-menu-item>

<dap-ds-navigation-menu-item>
  <dap-ds-button slot="trigger" href="/about" variant="subtle-menu" >
    About
  </dap-ds-button>
</dap-ds-navigation-menu-item>
</dap-ds-navigation-menu>
Mega Menu Layout

Create complex mega menus with grid layouts and organized content sections.

<dap-ds-navigation-menu fullWidth>
<dap-ds-navigation-menu-item>
  <dap-ds-button slot="trigger" href="/" variant="subtle-menu" >
    Home
  </dap-ds-button>
</dap-ds-navigation-menu-item>

<dap-ds-navigation-menu-item>
  <span slot="title">Services</span>
  
  <div style={{display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 'var(--dds-spacing-200)', padding: 'var(--dds-spacing-200)', minWidth: '400px'}}>
    <div>
      <dap-ds-typography variant="h4">
        Development
      </dap-ds-typography>
      <dap-ds-button href="/web-dev" variant="subtle-menu" >
        <dap-ds-icon name="design-tools-line"></dap-ds-icon>
        Web Development
      </dap-ds-button>
      <p style={{margin: 'var(--dds-spacing-200) 0 0 0', fontSize: 'var(--dds-font-size-sm)', color: 'var(--dds-color-text-secondary)'}}>
        Modern web applications
      </p>
      
      <dap-ds-button href="/mobile" variant="subtle-menu" >
        <dap-ds-icon name="device-computer-line"></dap-ds-icon>
        Mobile Development
      </dap-ds-button>
      <p style={{margin: 'var(--dds-spacing-200) 0 0 0', fontSize: 'var(--dds-font-size-sm)', color: 'var(--dds-color-text-secondary)'}}>
        iOS and Android apps
      </p>
    </div>
    <div>
      <dap-ds-typography variant="h4">
        Consulting
      </dap-ds-typography>
      <dap-ds-button href="/strategy" variant="subtle-menu" >
        <dap-ds-stack direction="row">
          <dap-ds-icon name="lightbulb-fill"></dap-ds-icon>
          Strategy
        </dap-ds-stack>
      </dap-ds-button>
      <p style={{margin: 'var(--dds-spacing-200) 0 0 0', fontSize: 'var(--dds-font-size-sm)', color: 'var(--dds-color-text-secondary)'}}>
        Technical planning
      </p>
      
      <dap-ds-button href="/audit" variant="subtle-menu" >
        <dap-ds-stack direction="row">
          <dap-ds-icon name="shield-check-line"></dap-ds-icon>
          Security Audit
        </dap-ds-stack>
      </dap-ds-button>
      <p style={{margin: 'var(--dds-spacing-200) 0 0 0', fontSize: 'var(--dds-font-size-sm)', color: 'var(--dds-color-text-secondary)'}}>
        Code review and security
      </p>
    </div>
  </div>
</dap-ds-navigation-menu-item>
</dap-ds-navigation-menu>
Multi-Level Nested Navigation

Navigation menus support unlimited nesting depth with automatic placement and keyboard navigation.

<dap-ds-navigation-menu>
<dap-ds-navigation-menu-item>
  <dap-ds-button slot="trigger" href="/" variant="subtle-menu">
    <dap-ds-stack direction="row">
      <dap-ds-icon name="home-6-line"></dap-ds-icon>
      Home
    </dap-ds-stack>
  </dap-ds-button>
</dap-ds-navigation-menu-item>

<dap-ds-navigation-menu-item>
  <span slot="title">Products</span>

  <dap-ds-navigation-menu-item>
    <span slot="title">Electronics</span>

    <dap-ds-navigation-menu-item>
      <span slot="title">Computers</span>

      <dap-ds-navigation-menu-item>
        <dap-ds-link slot="trigger" href="/products/electronics/computers/laptops">
          Laptops
        </dap-ds-link>
      </dap-ds-navigation-menu-item>

      <dap-ds-navigation-menu-item>
        <dap-ds-link slot="trigger" href="/products/electronics/computers/desktops">
          Desktops
        </dap-ds-link>
      </dap-ds-navigation-menu-item>
    </dap-ds-navigation-menu-item>

    <dap-ds-navigation-menu-item>
      <span slot="title">Mobile Devices</span>

      <dap-ds-navigation-menu-item>
        <dap-ds-link slot="trigger" href="/products/electronics/mobile/smartphones">
          Smartphones
        </dap-ds-link>
      </dap-ds-navigation-menu-item>
    </dap-ds-navigation-menu-item>
  </dap-ds-navigation-menu-item>
</dap-ds-navigation-menu-item>
</dap-ds-navigation-menu>
Custom Trigger Elements

Navigation items support custom trigger elements beyond standard buttons.

<dap-ds-navigation-menu>
<dap-ds-navigation-menu-item>
  <div slot="trigger" style={{
    padding: 'var(--dds-spacing-300) var(--dds-spacing-400)',
    borderRadius: 'var(--dds-radius-base)',
    cursor: 'pointer',
    background: 'var(--dds-background-neutral-base)',
    border: '1px solid var(--dds-border-neutral-subtle)',
    display: 'flex',
    alignItems: 'center',
    gap: 'var(--dds-spacing-200)'
  }}>
    <dap-ds-icon name="more-line"></dap-ds-icon>
    Custom Trigger
  </div>
  
  <div style={{padding: 'var(--dds-spacing-200)'}}>
    <dap-ds-button href="/option1" variant="subtle-menu" >
      Option 1
    </dap-ds-button>
    <dap-ds-button href="/option2" variant="subtle-menu" >
      Option 2
    </dap-ds-button>
  </div>
</dap-ds-navigation-menu-item>
</dap-ds-navigation-menu>
Custom Indicator Icon

Customize the expand indicator icon using the indicator slot.

<dap-ds-navigation-menu>
<dap-ds-navigation-menu-item>
  <span slot="title">Products</span>
  <dap-ds-icon slot="indicator" name="heart-fill"></dap-ds-icon>
  
  <dap-ds-stack spacing="100">
    <dap-ds-button href="/web-dev" variant="subtle-menu-item">
      Web Development
    </dap-ds-button>
    <dap-ds-button href="/mobile" variant="subtle-menu-item">
      Mobile Apps
    </dap-ds-button>
  </dap-ds-stack>
</dap-ds-navigation-menu-item>
</dap-ds-navigation-menu>
Real-World Patterns Main Site Navigation

Implementation of a complete site navigation with branding and user actions.

<header style={{borderBottom: '1px solid var(--dds-border-neutral-subtle)', padding: 'var(--dds-spacing-200)'}}>
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'space-between', maxWidth: '1200px', margin: '0 auto'}}>
  <div style={{display: 'flex', alignItems: 'center', gap: 'var(--dds-spacing-200)'}}>
    <dap-ds-typography variant="h4">
      Your Brand
    </dap-ds-typography>
    
    <dap-ds-navigation-menu activeHref="/products">
      <dap-ds-navigation-menu-item>
        <dap-ds-button slot="trigger" href="/" variant="subtle-menu" >
          Home
        </dap-ds-button>
      </dap-ds-navigation-menu-item>
      
      <dap-ds-navigation-menu-item baseHref="/products">
        <span slot="title">Products</span>
          
          <dap-ds-stack spacing="100">
            <dap-ds-button href="/web-dev" variant="subtle-menu-item">
              <dap-ds-stack spacing="0">
                <dap-ds-stack direction="row">
                  <dap-ds-icon name="tools-line"></dap-ds-icon>
                  Web Development
                </dap-ds-stack>
                <dap-ds-typography variant="description">
                  Build modern web applications
                </dap-ds-typography>
              </dap-ds-stack>
            </dap-ds-button>

            <dap-ds-button href="/mobile" variant="subtle-menu-item">
              <dap-ds-stack spacing="0">
                <dap-ds-stack direction="row">
                  <dap-ds-icon name="cookie-line"></dap-ds-icon>
                  Mobile Apps
                </dap-ds-stack>
                <dap-ds-typography variant="description">
                  iOS and Android development
                </dap-ds-typography>
              </dap-ds-stack>
            </dap-ds-button>
          </dap-ds-stack>
        </dap-ds-navigation-menu-item>
      
        <dap-ds-navigation-menu-item>
          <dap-ds-button slot="trigger" href="/about" variant="subtle-menu" >
            About
          </dap-ds-button>
        </dap-ds-navigation-menu-item>
    </dap-ds-navigation-menu>
  </div>
  
  <dap-ds-button variant="primary" href="/contact">
    Get Started
  </dap-ds-button>
</div>
</header>
Custom Styling

The navigation menu component can be customized using CSS custom properties for layout spacing and popup appearance.

Custom Styling Example
<dap-ds-navigation-menu class="custom-navigation" activeHref="/products">
<dap-ds-navigation-menu-item class="custom-navigation-item">
  <dap-ds-button slot="trigger" href="/" variant="subtle-menu">
    <dap-ds-stack direction="row">
      <dap-ds-icon name="home-6-line"></dap-ds-icon>
      Home
    </dap-ds-stack>
  </dap-ds-button>
</dap-ds-navigation-menu-item>

<dap-ds-navigation-menu-item baseHref="/products" class="custom-navigation-item">
  <span slot="title">Products</span>
  
  <dap-ds-stack spacing="100">
    <dap-ds-button href="/web-dev" variant="subtle-menu-item">
      <dap-ds-stack spacing="0">
        <dap-ds-stack direction="row">
          <dap-ds-icon name="tools-line"></dap-ds-icon>
          Web Development
        </dap-ds-stack>
        <dap-ds-typography variant="description">
          Custom styled dropdown item
        </dap-ds-typography>
      </dap-ds-stack>
    </dap-ds-button>

    <dap-ds-button href="/mobile" variant="subtle-menu-item">
      <dap-ds-stack spacing="0">
        <dap-ds-stack direction="row">
          <dap-ds-icon name="cookie-line"></dap-ds-icon>
          Mobile Apps
        </dap-ds-stack>
        <dap-ds-typography variant="description">
          Enhanced styling example
        </dap-ds-typography>
      </dap-ds-stack>
    </dap-ds-button>
  </dap-ds-stack>
</dap-ds-navigation-menu-item>

<dap-ds-navigation-menu-item class="custom-navigation-item">
  <dap-ds-button slot="trigger" href="/contact" variant="subtle-menu">
    Contact
  </dap-ds-button>
</dap-ds-navigation-menu-item>
</dap-ds-navigation-menu>
.custom-navigation {
    /* Increase spacing between navigation items */
    --dds-navigation-menu-item-gap: var(--dds-spacing-300);
}

.custom-navigation-item {
  /* Customize dropdown appearance */
  --dds-popup-background: var(--dds-background-neutral-subtle);
  --dds-popup-border-radius: var(--dds-radius-large);
  --dds-popup-border-color: red;
  --dds-popup-border-width: 2px;
  --dds-popup-padding: var(--dds-spacing-400);
}
  
.custom-navigation-item dap-ds-button[variant="subtle-menu"] {
  /* Custom button styling for menu items */
  --dds-button-padding-x: var(--dds-spacing-400);
  --dds-button-padding-y: var(--dds-spacing-300);
  --dds-button-border-radius: var(--dds-radius-large);
  
  /* Hover and active states */
  --dds-button-subtle-background-neutral-hover: var(--dds-indigo-600);
  --dds-button-subtle-background-neutral-pressed: var(--dds-indigo-700);
  --dds-button-subtle-text-neutral-hover: var(--dds-button-primary-text-enabled);
}

.custom-navigation-item dap-ds-button[variant="subtle-menu-item"] {
  /* Custom styling for dropdown menu items */
  --dds-button-subtle-menu-item-padding: var(--dds-spacing-300);
  --dds-button-subtle-menu-item-border-radius: var(--dds-radius-base);
  --dds-button-subtle-menu-item-color-bg-hover: var(--dds-indigo-600);
}

Accessibility Built-in Features
  • Full keyboard navigation with Arrow keys, Tab, Enter, and Escape
  • Screen reader support with proper ARIA roles and labels
  • Focus management with automatic dropdown closure
  • Active state announcements for current page/section
Keyboard Navigation Top-Level Items
  • Tab: Navigate between top-level items
  • ArrowLeft/ArrowRight (horizontal): Navigate between items
  • ArrowUp/ArrowDown (vertical): Navigate between items
  • ArrowDown/ArrowUp (horizontal): Open submenu if item has one
  • ArrowRight (vertical): Open submenu if item has one
  • Enter/Space: Activate current item (open submenu or navigate)
  • Home/End: Jump to first/last item
Nested Items
  • ArrowDown: Move to next sibling
  • ArrowUp: Move to previous sibling
  • ArrowRight: Open nested submenu or move into submenu
  • ArrowLeft: Close parent submenu and return focus
  • Escape: Close parent submenu
  • Enter/Space: Activate link or open submenu
ARIA Support

The component automatically provides:

  • Semantic <nav> element (no menu/menubar roles - this is navigation, not application menu)
  • aria-current="page" for active navigation items
  • aria-expanded states for dropdown triggers
  • aria-haspopup for items with submenus
  • aria-controls linking triggers to their dropdowns
  • Screen readers announce as navigation landmark
Interaction Behavior Hover Behavior
  • Mouse Hover: When hovering over a navigation item with a submenu, a 100ms delay timer starts. If the mouse stays, the submenu opens automatically.
  • Sibling Management: When hovering over a different item, sibling items' submenus are automatically closed to ensure only one submenu is open at a time.
  • Click After Hover: If a submenu was opened by hover and you click it, the submenu stays open (doesn't toggle closed). The hover flag is cleared so future clicks will toggle normally.
Click Behavior
  • Simple Links: Clicking navigates to the href
  • Items with Submenus:
    • First click opens the submenu
    • Second click closes it (toggle behavior)
    • If opened by hover first, clicking keeps it open
Active State Management

Items can be marked as active using different matching strategies:

  • Exact Match: href === activeHref (default)
  • Prefix Match: Use baseHref property for prefix matching - item will be active if activeHref.startsWith(baseHref)
  • Exact Only: Set exactHref="true" to require exact match even when baseHref is set
<!-- Prefix matching example -->
<dap-ds-navigation-menu activeHref="/products/web-dev">
  <dap-ds-navigation-menu-item baseHref="/products">
    <!-- This item will be active because /products/web-dev starts with /products -->
    <span slot="title">Products</span>
  </dap-ds-navigation-menu-item>
</dap-ds-navigation-menu>
Technical Details

The navigation menu component is built on top of the popup component, combining navigation semantics with positioning capabilities. It automatically manages:

  • Active states based on href matching
  • Dropdown interactions with hover delay and click behavior
  • Keyboard navigation with full arrow key support
  • Nested item management with automatic level and placement calculation
  • Sibling coordination to ensure proper submenu behavior
  • Positioning that escapes constrained containers using fixed positioning strategy

The component uses Floating UI for intelligent positioning and automatically adjusts placement based on nesting level and orientation.

Importing
import { DapDSNavigationMenu } from 'dap-design-system'
Importing React
import { DapDSNavigationMenuReact } from 'dap-design-system/react'
Tree-Shakeable Imports

For optimal bundle sizes, use the tree-shakeable import syntax:

import { DapDSNavigationMenu } from 'dap-design-system/components'
Attributes
PropertyTypeDefaultDescription
activeHrefstringThe currently active href for highlighting active navigation items with aria-current="page". Defaults to window.location.pathname if not provided.
orientation'horizontal', 'vertical''horizontal'The orientation of the navigation menu. Default is 'horizontal'.
fullWidthbooleanfalseWhether the navigation menu should take full width of the screen. Default is false.
allowMultipleOpenbooleantrueWhether multiple dropdown branches can stay open simultaneously (accordion mode). Default is true.
Slots
NameDescription
(default)The navigation menu list and items.
Events
Event NameDescriptionType
dds-navigation-item-clickFired when a navigation item is clicked.{href: string, event: Event }
CSS Parts
Part NameDescription
baseThe main navigation menu container (nav element).
How to Use CSS Parts

You can style CSS parts using the ::part() pseudo-element selector:

/* Target a specific part */
.my-custom-dap-ds-navigation-menu::part(base) {
  /* Your custom styles */
}

Example usage:

<dap-ds-navigation-menu class="my-custom-dap-ds-navigation-menu">
  Navigation menu
</dap-ds-navigation-menu>
.my-custom-dap-ds-navigation-menu::part(base) {
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

CSS parts allow you to style internal elements of the component while maintaining encapsulation. Learn more in our styling guide.

CSS Custom Properties
Property NameDescription
--dds-navigation-menu-item-gapThe gap between navigation menu items. (default: var(--dds-spacing-100)).
How to Use CSS Custom Properties

CSS custom properties (CSS variables) can be set directly on the component or in your stylesheet:

Method 1: Inline styles (Quick customization)

<dap-ds-navigation-menu
  style="--dds-navigation-menu-item-gap: value; ">
  Navigation menu
</dap-ds-navigation-menu>

Method 2: CSS classes (Reusable styles)

.my-custom-dap-ds-navigation-menu {
  --dds-navigation-menu-item-gap: value;
}
<dap-ds-navigation-menu class="my-custom-dap-ds-navigation-menu">
  Navigation menu
</dap-ds-navigation-menu>

Method 3: Global theme customization

/* Apply to all instances */
dap-ds-navigation-menu {
  --dds-navigation-menu-item-gap: value;
}

CSS custom properties inherit through the Shadow DOM, making them perfect for theming. Changes apply immediately without rebuilding.

Components Navigation Menu Item <dap-ds-navigation-menu-item/> Attributes
PropertyTypeDefaultDescription
disabledbooleanfalseThe disabled state of the popup. Default is false.
openedbooleanfalseThe open state of the popup. Default is false.
placement'top', 'right' , 'bottom' , 'left' , 'top-start' , 'top-end' , 'bottom-start' , 'bottom-end' , 'left-start' , 'left-end' , 'right-start' , 'right-end''bottom-start'The placement of the popup (automatically adjusted based on nesting level). Default is 'bottom-start'.
floatingStrategy'absolute', 'fixed''fixed'The floating strategy of the popup. Default is 'fixed'.
offsetnumber0The offset of the popup. Default is 0.
syncbooleanfalseWhether the popup should sync its width with the trigger. Default is false.
maxHeightnumber, 'auto'250The maximum height of the popup. Default is 250.
maxWidthnumber, 'auto''auto'The maximum width of the popup. Default is 'auto'.
hasArrowbooleanfalseWhether the popup has an arrow. Default is false.
overflowbooleantrueWhether the popup should overflow. Default is true.
fullWidthbooleanfalseWhether the popup should take full width of the screen. Default is false.
iconstringThe name of the icon to display in the trigger.
ariaLabelledBystringThe name of the element that labels the navigation dropdown.
activeHrefstringThe href of the navigation item that is active (receives aria-current="page").
baseHrefstringThe href of the navigation item. If provided, the navigation item will be active if the href is a substring of the activeHref.
exactHrefbooleanfalseWhether the navigation item should be active if the href is exactly the same as the activeHref. Default is false.
levelnumber0The nesting level of this navigation item (0 = top-level, automatically set for nested items). Default is 0.
orientation'horizontal', 'vertical''horizontal'The orientation of the parent navigation menu (automatically inherited). Default is 'horizontal'.
hasContentbooleanfalse
size'xs', 'sm' , 'lg'The size of the popup. Default is 'sm'.
Slots
NameDescription
triggerThe trigger element (link, button, etc.) for this navigation item.
titleThe title of the navigation item.
indicatorThe expand indicator icon (defaults to arrow icon based on orientation and level).
(default)The dropdown content (can contain nested dap-ds-navigation-menu-item elements).
Events
Event NameDescriptionType
dds-navigation-item-clickFired when a navigation item is clicked.{href: string, event: Event }
dds-navigation-dropdown-openFired when a navigation dropdown is opened.{item: DapDSNavigationMenuItem }
CSS Parts
Part NameDescription
baseThe base part of the navigation item.
triggerThe trigger element part.
contentThe dropdown content part.
indicator-iconThe expand indicator icon part.
CSS Custom Properties
Property NameDescription
--dds-navigation-menu-item-spacingThe padding/spacing of the navigation menu item content. (default: var(--dds-spacing-200)).
--dds-navigation-menu-item-border-widthThe border width of the navigation menu item content. (default: var(--dds-border-width-base)).
--dds-navigation-menu-item-border-colorThe border color of the navigation menu item content. (default: var(--dds-border-neutral-subtle)).
--dds-navigation-menu-item-border-radiusThe border radius of the navigation menu item content. (default: var(--dds-radius-base)).
--dds-navigation-menu-item-backgroundThe background color of the navigation menu item content. (default: var(--dds-background-neutral-base)).
--dds-navigation-menu-item-shadowThe box shadow of the navigation menu item content. (default: var(--dds-shadow-base)).