Primitives
A menu is a list of options or commands presented to the user in a dropdown list.
Import the Menu primitives from ng-primitives/menu.
import { NgpMenu, NgpMenuItem, NgpMenuTrigger, NgpSubmenuTrigger } from 'ng-primitives/menu';
Assemble the menu directives in your template.
<button [ngpMenuTrigger]="menu" ngpButton></button>
<ng-template #menu>
<div ngpMenu>
<button ngpMenuItem>Item 1</button>
<button ngpMenuItem>Item 2</button>
<button ngpMenuItem>Item 3</button>
</div>
</ng-template>
Create reusable components that use the NgpMenu directive.
Generate a reusable menu component using the Angular CLI.
ng g ng-primitives:primitive menu
path: The path at which to create the component file.prefix: The prefix to apply to the generated component selector.componentSuffix: The suffix to apply to the generated component class name.fileSuffix: The suffix to apply to the generated component file name. Defaults to component.exampleStyles: Whether to include example styles in the generated component file. Defaults to true.Here are some additional examples of how to use the Menu primitives.
The menu can contain submenus, which are nested menus that can be opened by hovering on a menu item.
You can customize the offset using either a simple number or an object for more precise control:
<!-- Simple number offset -->
<button [ngpMenuTrigger]="menu" ngpMenuTriggerOffset="12">Menu with 12px offset</button>
<!-- Object offset for precise control -->
<button
[ngpMenuTrigger]="menu"
[ngpMenuTriggerOffset]="{mainAxis: 8, crossAxis: 4, alignmentAxis: 2}"
>
Menu with custom offset
</button>
You can customize the shift behavior to control how the menu stays within the viewport:
<!-- Disable shift -->
<button [ngpMenuTrigger]="menu" [ngpMenuTriggerShift]="false">Menu without shift</button>
<!-- Object shift for precise control -->
<button [ngpMenuTrigger]="menu" [ngpMenuTriggerShift]="{padding: 8}">
Menu with custom shift padding
</button>
The following directives are available to import from the ng-primitives/menu package:
The following data attributes are available on the NgpMenuTrigger directive:
| Attribute | Description |
|---|---|
data-open |
Applied when the menu is open. |
The following data attributes are available on the NgpMenu directive:
| Attribute | Description |
|---|---|
data-enter |
Applied when the menu is being added to the DOM. This can be used to trigger animations. |
data-exit |
Applied when the menu is being removed from the DOM. This can be used to trigger animations. |
data-placement |
The final rendered placement of the menu. |
The following CSS custom properties are applied to the ngpMenu directive:
| Property | Description |
|---|---|
--ngp-menu-transform-origin |
The transform origin of the menu for animations. |
--ngp-menu-trigger-width |
The width of the trigger element. |
The following data attributes are available on the NgpMenuItem directive:
| Attribute | Description |
|---|---|
data-disabled |
Applied when the item is disabled. |
The following data attributes are available on the NgpSubmenuTrigger directive:
| Attribute | Description |
|---|---|
data-open |
Applied when the submenu is open. |
For the menu to be positioned correctly relative to the trigger element, it should use fixed positioning. For example, you can use the following CSS:
[ngpMenu] {
position: fixed;
}
The ngpMenu primitive adds a CSS custom property --ngp-menu-transform-origin to the element that can be used to animate the menu from the trigger element.
The ngpMenu will also add the data-enter and data-exit attributes to the element when it is being added or removed from the DOM. This can be used to trigger animations.
:host[data-enter] {
animation: fade-in 0.2s ease-in-out;
}
:host[data-exit] {
animation: fade-out 0.2s ease-in-out;
}
You can configure the default options for all menus in your application by using the provideMenuConfig function in a providers array.
import { provideMenuConfig } from 'ng-primitives/menu';
bootstrapApplication(AppComponent, {
providers: [
provideMenuConfig({
offset: 4,
placement: 'top',
flip: true,
container: document.body,
scrollBehavior: 'reposition',
}),
],
});
Number format: offset: 8 - Applies to mainAxis (distance from trigger)
Object format:
offset: {
mainAxis: 8, // Distance between menu and trigger element
crossAxis: 4, // Skidding along the alignment axis
alignmentAxis: 2 // Same as crossAxis but for aligned placements
}
Boolean format: shift: false - Disables shift behavior
Object format:
shift: {
padding: 8, // Minimum padding between menu and viewport edges
limiter: { // Optional limiter to control shifting behavior
fn: limitShift,
options: { /* limiter options */ }
}
}
Adhere to the WAI-ARIA Authoring Practices for menus and submenus.
Copyright © 2026 Angular Primitives
This site is powered by Netlify