Primitives

Tooltip

Display additional information on hover.

Import

Import the Tooltip primitives from ng-primitives/tooltip.

import { NgpTooltip, NgpTooltipTrigger, NgpTooltipArrow } from 'ng-primitives/tooltip';

Usage

Assemble the tooltip directives in your template.

<button [ngpTooltipTrigger]="tooltip" ngpButton>Hover me</button>

<ng-template #tooltip>
  <div ngpTooltip>Tooltip content</div>
</ng-template>

Reusable Component

Create a tooltip component that uses the NgpTooltip directive.

Schematics

Generate a reusable tooltip component using the Angular CLI.

ng g ng-primitives:primitive tooltip

Options

  • 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.
  • styles: How component styles should be generated. css (default) includes the full example styles; unstyled omits them entirely so you can style the component yourself.
  • example-styles (deprecated): still supported for compatibility - true maps to styles: css, false maps to styles: unstyled.

Examples

Tooltip with Custom Container

The tooltip can be rendered inside a custom container. You can open DevTools and inspect the DOM to see it mounted within this container.

Cursor-Following Tooltip

You can position a tooltip at specific coordinates using the ngpTooltipTriggerPosition input. Combined with ngpTooltipTriggerTrackPosition, this enables smooth cursor-following tooltips.

Custom Offset

You can customize the offset using either a simple number or an object for more precise control:

<!-- Simple number offset -->
<button [ngpTooltipTrigger]="tooltip" ngpTooltipTriggerOffset="12">Tooltip with 12px offset</button>

<!-- Object offset for precise control -->
<button
  [ngpTooltipTrigger]="tooltip"
  [ngpTooltipTriggerOffset]="{mainAxis: 8, crossAxis: 4, alignmentAxis: 2}"
>
  Tooltip with custom offset
</button>

Custom Anchor

You can provide a separate anchor element using ngpTooltipTriggerAnchor to control where the tooltip appears while keeping the full trigger area interactive.

The anchor is live - rebinding it moves a tooltip that is already showing to the new element.

Custom Shift

You can customize the shift behavior to control how the tooltip stays within the viewport:

<!-- Disable shift -->
<button [ngpTooltipTrigger]="tooltip" [ngpTooltipTriggerShift]="false">
  Tooltip without shift
</button>

<!-- Object shift for precise control -->
<button [ngpTooltipTrigger]="tooltip" [ngpTooltipTriggerShift]="{padding: 8}">
  Tooltip with custom shift padding
</button>

Overflow Boundary

By default, the tooltip is kept within the viewport and its clipping ancestors. Pass boundary or rootBoundary to flip or shift to measure overflow against something else:

<!-- Keep the tooltip inside a container element -->
<div #boundary>
  <button [ngpTooltipTrigger]="tooltip" [ngpTooltipTriggerFlip]="{boundary: boundary}">
    Tooltip constrained to a container
  </button>
</div>

<!-- Keep the tooltip inside whatever scrolls the trigger -->
<div style="overflow: auto">
  <button [ngpTooltipTrigger]="tooltip" [ngpTooltipTriggerFlip]="{altBoundary: true}">
    Tooltip constrained to the trigger's scroll container
  </button>
</div>

<!-- Measure against the whole document rather than the viewport -->
<button [ngpTooltipTrigger]="tooltip" [ngpTooltipTriggerFlip]="{rootBoundary: 'document'}">
  Tooltip that does not flip while off-screen
</button>

altBoundary measures against the trigger's clipping ancestors rather than the tooltip's. The tooltip is portalled to the body, so its own clipping ancestors are effectively the viewport - set this when the trigger sits in a scroll container. It applies only while boundary is left at its default; an explicit boundary always wins.

crossAxis widens the axis each option checks. For flip it is the alignment axis, on by default - that is how bottom-end becomes bottom-start near an edge. For shift it is the side axis, off by default; enabling it lets the panel move along the placement direction too:

<button [ngpTooltipTrigger]="tooltip" [ngpTooltipTriggerFlip]="{crossAxis: false}">
  Keep the alignment
</button>
<button [ngpTooltipTrigger]="tooltip" [ngpTooltipTriggerShift]="{crossAxis: true}">
  Shift on both axes
</button>

The --ngp-tooltip-available-width and --ngp-tooltip-available-height custom properties are measured against the flip boundary, or the shift boundary when flip does not set one.

Using Text Content as Tooltip

The useTextContent input (enabled by default) allows the tooltip to automatically use the text content of the trigger element as the tooltip content. This is particularly useful for displaying full text when content is truncated with ellipsis.

<!-- Simple usage - uses text content automatically -->
<div class="truncated-text" ngpTooltipTrigger>
  This text might be truncated with ellipsis and show the full content in the tooltip
</div>

<!-- Passing content directly takes precedence -->
<button [ngpTooltipTrigger]="myToolip">This won't show a tooltip unless content is provided</button>

Important: Global Styles Required

When using the useTextContent feature or string values, the tooltip styles must be global and not encapsulated to the component. This is because the tooltip content is rendered in a portal outside of your component's scope.

/* ✅ Global styles (in styles.css or with ViewEncapsulation.None) */
[ngpTooltip] {
  position: absolute;
  background-color: #333;
  color: white;
  padding: 8px 12px;
  border-radius: 4px;
  font-size: 14px;
}

/* ❌ Encapsulated styles won't work with useTextContent */
.my-component [ngpTooltip] {
  /* This won't be applied to text content tooltips */
}

If you need component-scoped styles, use template-based or component-based tooltips instead of useTextContent.

Show on Overflow

The showOnOverflow input allows you to show tooltips only when the trigger element has overflowing content. This is particularly useful for text that might be truncated with ellipsis.

<div
  class="truncated-text"
  appTooltipTrigger="This tooltip only shows when text overflows"
  ngpTooltipTriggerShowOnOverflow
>
  This text might be truncated
</div>

Overflow is measured each time the tooltip is about to show, so a trigger whose content changes without the element resizing is handled correctly.

Hoverable Tooltip Content

Tooltips keep strict tooltip semantics (role="tooltip") while supporting pointer movement from trigger to tooltip content.

Use ngpTooltipTriggerHoverableContent to control whether hovering tooltip content keeps it open:

<!-- Default: closes when pointer leaves trigger -->
<button [ngpTooltipTrigger]="tooltip">Default behavior</button>

<!-- Opt in: stays open while pointer moves into tooltip content -->
<button [ngpTooltipTrigger]="tooltip" ngpTooltipTriggerHoverableContent="true">
  Hover bridge enabled
</button>

If tooltip content needs to be interactive or focusable, use Popover instead.

API Reference

The following directives are available to import from the ng-primitives/tooltip package:

NgpTooltip

NgpTooltipTrigger

NgpTooltipArrow

The NgpTooltipArrow directive is used to add an arrow to the tooltip. It should be placed inside the tooltip content. It will receive inset-inline-start or inset-block-start styles to position the arrow based on the tooltip's placement. As a result it should be positioned absolutely within the tooltip content.

The arrow can be styled conditionally based on the tooltip's final placement using the data-placement attribute:

[ngpTooltipArrow][data-placement='top'] {
  /* Arrow styles when tooltip is positioned on top */
}

[ngpTooltipArrow][data-placement='bottom'] {
  /* Arrow styles when tooltip is positioned on bottom */
}

Styling

For the tooltip to be positioned correctly relative to the trigger element, it must use absolute or fixed positioning. For example, you can use the following CSS:

[ngpTooltip] {
  position: absolute;
}

Animations

The ngpTooltip primitive adds a CSS custom property --ngp-tooltip-transform-origin to the element that can be used to animate the tooltip from the trigger element.

The ngpTooltip 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;
}

Global Configuration

You can configure the default options for all tooltips in your application by using the provideTooltipConfig function in a providers array.

import { provideTooltipConfig } from 'ng-primitives/tooltip';

bootstrapApplication(AppComponent, {
  providers: [
    provideTooltipConfig({
      offset: 4,
      placement: 'top',
      showDelay: 0,
      hideDelay: 500,
      flip: true,
      container: document.body,
      showOnOverflow: false,
      useTextContent: true,
      scrollBehavior: 'reposition',
      cooldown: 300,
      hoverableContent: false,
    }),
  ],
});

NgpTooltipConfig

Accessibility

The tooltip primitive follows the WAI-ARIA Tooltip pattern. The tooltip element is assigned role="tooltip" and the trigger element is linked to the tooltip via aria-describedby.

Keyboard Interactions

  • Tab: Focus the trigger element to show the tooltip.
  • Esc: Dismiss the tooltip.

Copyright © 2026 Angular Primitives

This site is powered by Netlify