Primitives
A navigation menu component for site-wide navigation with dropdown content panels.
Import the Navigation Menu primitives from ng-primitives/navigation-menu.
import {
NgpNavigationMenu,
NgpNavigationMenuList,
NgpNavigationMenuItem,
NgpNavigationMenuTrigger,
NgpNavigationMenuContent,
NgpNavigationMenuContentItem,
NgpNavigationMenuLink,
} from 'ng-primitives/navigation-menu';
Assemble the navigation menu directives in your template.
<nav ngpNavigationMenu>
<ul ngpNavigationMenuList>
<li ngpNavigationMenuItem>
<button [ngpNavigationMenuTrigger]="productsMenu">Products</button>
<ng-template #productsMenu>
<div ngpNavigationMenuContent>
<a ngpNavigationMenuContentItem href="/analytics">Analytics</a>
<a ngpNavigationMenuContentItem href="/automation">Automation</a>
<a ngpNavigationMenuContentItem href="/insights">Insights</a>
</div>
</ng-template>
</li>
<li>
<a ngpNavigationMenuLink href="/pricing">Pricing</a>
</li>
<li>
<a ngpNavigationMenuLink href="/about">About</a>
</li>
</ul>
</nav>
A vertical navigation menu is useful for sidebar navigation. Use the ngpNavigationMenuOrientation input to change the orientation and adjust the trigger placement accordingly.
The following directives are available to import from the ng-primitives/navigation-menu package:
The root container for the navigation menu. Apply this to a <nav> element for proper semantics.
A container for navigation menu items. It manages roving focus between menu triggers and links.
A container for a menu trigger and its content. It manages the open/close state for a specific menu item.
A button that opens navigation menu content on hover/focus.
The dropdown panel displayed when a trigger is activated.
A standalone navigation link within the menu list.
The navigation menu uses role="navigation" on the container, aria-haspopup="menu" and aria-expanded on triggers, and role="menu" with aria-labelledby on content panels. This follows the WAI-ARIA Navigation Menu pattern.
| Key | Action |
|---|---|
ArrowRight / ArrowLeft |
Navigate between triggers (horizontal orientation) |
ArrowUp / ArrowDown |
Navigate between triggers (vertical orientation) |
ArrowDown (horizontal) |
Open content and focus first item |
ArrowRight (vertical) |
Open content and focus first item |
Enter / Space |
Open content and focus first item, or activate link |
Escape |
Close content and return focus to trigger |
Home / End |
Navigate to first/last trigger |
Tab |
Move focus out of the navigation menu |
The navigation menu content uses a portal and should be positioned using position: fixed or position: absolute.
[ngpNavigationMenuContent] {
position: fixed;
background: white;
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 16px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
The content panel supports enter/exit animations using the data-enter and data-exit attributes.
[ngpNavigationMenuContent][data-enter] {
animation: fade-in 0.2s ease-out;
}
[ngpNavigationMenuContent][data-exit] {
animation: fade-out 0.15s ease-in;
}
When users quickly move between menu triggers, the cooldown feature provides instant transitions without animation delays. During the cooldown period (default 300ms), the previous menu is immediately removed and the new menu appears instantly.
Use the data-instant attribute in CSS to handle these instant transitions:
/* Skip animations during instant transitions */
[ngpNavigationMenuContent][data-instant][data-enter],
[ngpNavigationMenuContent][data-instant][data-exit] {
animation: none;
}
To disable cooldown and always show animations, set cooldown to 0 on the trigger:
<button [ngpNavigationMenuTrigger]="menu" [ngpNavigationMenuTriggerCooldown]="0">Menu</button>
You can configure the default options for all navigation menus in your application using the provideNavigationMenuConfig function.
import { provideNavigationMenuConfig } from 'ng-primitives/navigation-menu';
bootstrapApplication(AppComponent, {
providers: [
provideNavigationMenuConfig({
orientation: 'horizontal',
showDelay: 200,
hideDelay: 150,
placement: 'bottom-start',
offset: 4,
flip: true,
shift: true,
wrap: true,
cooldown: 300,
}),
],
});
Copyright © 2026 Angular Primitives
This site is powered by Netlify