Primitives
Display arbitrary content inside floating panels.
Import the Popover primitives from ng-primitives/popover.
import { NgpPopover, NgpPopoverTrigger, NgpPopoverArrow } from 'ng-primitives/popover';
Assemble the popover directives in your template.
<button [ngpPopoverTrigger]="popover" (ngpPopoverTriggerOpenChange)="onPopoverStateChange($event)">
Click me
</button>
<ng-template #popover>
<div ngpPopover>Popover content</div>
</ng-template>
You can listen to the ngpPopoverTriggerOpenChange event to perform actions when the popover state changes. The event emits a boolean value indicating whether the popover is open or closed:
You can customize the offset using either a simple number or an object for more precise control:
<!-- Simple number offset -->
<button [ngpPopoverTrigger]="popover" ngpPopoverTriggerOffset="12">Popover with 12px offset</button>
<!-- Object offset for precise control -->
<button
[ngpPopoverTrigger]="popover"
[ngpPopoverTriggerOffset]="{mainAxis: 8, crossAxis: 4, alignmentAxis: 2}"
>
Popover with custom offset
</button>
You can customize the shift behavior to control how the popover stays within the viewport:
<!-- Disable shift -->
<button [ngpPopoverTrigger]="popover" [ngpPopoverTriggerShift]="false">
Popover without shift
</button>
<!-- Object shift for precise control -->
<button [ngpPopoverTrigger]="popover" [ngpPopoverTriggerShift]="{padding: 8}">
Popover with custom shift padding
</button>
Create a popover component that uses the NgpPopover directive.
Generate a reusable tooltip component using the Angular CLI.
ng g ng-primitives:primitive popover
path: The path at which to create the component file.prefix: The prefix to apply to the generated component selector.component-suffix: The suffix to apply to the generated component class name.file-suffix: The suffix to apply to the generated component file name. Defaults to component.example-styles: Whether to include example styles in the generated component file. Defaults to trueThe popover can be anchored to a different element than the trigger.
Use dismiss guards to prevent a popover from closing when there are unsaved changes. The closeOnOutsideClick and closeOnEscape options accept a guard function that returns a boolean or a Promise.
The following directives are available to import from the ng-primitives/popover package:
The NgpPopoverArrow directive is used to add an arrow to the popover. It should be placed inside the popover content. It will receive inset-inline-start or inset-block-start styles to position the arrow based on the popover's placement. As a result it should be positioned absolutely within the popover content.
The arrow can be styled conditionally based on the popover's final placement using the data-placement attribute:
[ngpPopoverArrow][data-placement='top'] {
/* Arrow styles when popover is positioned on top */
}
[ngpPopoverArrow][data-placement='bottom'] {
/* Arrow styles when popover is positioned on bottom */
}
For the popover to be positioned correctly relative to the trigger element, it must use absolute or fixed positioning. For example, you can use the following CSS:
[ngpPopover] {
position: absolute;
}
The ngpPopover primitive adds a CSS custom property --ngp-popover-transform-origin to the element that can be used to animate the popover from the trigger element.
The ngpPopover 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 popovers in your application by using the providePopoverConfig function in a providers array.
import { providePopoverConfig } from 'ng-primitives/popover';
bootstrapApplication(AppComponent, {
providers: [
providePopoverConfig({
offset: 4,
placement: 'top',
showDelay: 0,
hideDelay: 0,
flip: true,
container: document.body,
closeOnOutsideClick: true,
scrollBehavior: 'reposition',
cooldown: 0,
}),
],
});
The popover element is assigned role="dialog" and the trigger element uses aria-expanded to indicate the popover's open state. The trigger is linked to the popover via aria-describedby. Focus is trapped within the popover when open.
Copyright © 2026 Angular Primitives
This site is powered by Netlify