Skip to content
Ndop UI

Tooltip

A popup that displays information related to an element when it receives keyboard focus or the mouse hovers over it.

import { Component } from '@angular/core';
import { Button } from '@/ui/button/button';
import {
  Tooltip,
  TooltipPortal,
  TooltipTrigger,
  TooltipContent,
} from '@/ui/tooltip/tooltip';

/** A tooltip describing a button, shown on hover and keyboard focus. */
@Component({
  selector: 'example-tooltip-demo',
  imports: [Tooltip, TooltipTrigger, TooltipPortal, TooltipContent, Button],
  template: `
    <ng-container ndTooltip>
      <button ndButton ndTooltipTrigger variant="outline">Hover</button>
      <ng-template ndTooltipPortal>
        <div ndTooltipContent>Add to library</div>
      </ng-template>
    </ng-container>
  `,
})
export class TooltipDemoExample {}

A tooltip shows a short text label for an element when it is hovered or focused, after a short delay. It describes the trigger through aria-describedby, stays open while the pointer is over it, and closes on Escape, as WCAG 1.4.13 requires. It never takes focus, so it can't hold links or buttons.

Installation

npx @ndop/cli add tooltip

Usage

import { Button } from '@/ui/button/button';
import {
  Tooltip,
  TooltipPortal,
  TooltipTrigger,
  TooltipContent,
} from '@/ui/tooltip/tooltip';
<ng-container ndTooltip>
  <button ndButton ndTooltipTrigger variant="outline">Hover</button>
  <ng-template ndTooltipPortal>
    <div ndTooltipContent>Add to library</div>
  </ng-template>
</ng-container>

Examples

Tooltip icon button

An icon-only button with its own accessible name and a tooltip on the end side for sighted users.

import { Component } from '@angular/core';
import { NdIcon } from '@ndop/core';
import { Button } from '@/ui/button/button';
import {
  Tooltip,
  TooltipPortal,
  TooltipTrigger,
  TooltipContent,
} from '@/ui/tooltip/tooltip';

/**
 * An icon-only button with its own accessible name and a tooltip on the
 * end side for sighted users.
 */
@Component({
  selector: 'example-tooltip-icon-button',
  imports: [
    Tooltip,
    TooltipTrigger,
    TooltipPortal,
    TooltipContent,
    Button,
    NdIcon,
  ],
  template: `
    <ng-container ndTooltip [openDelay]="300">
      <button
        ndButton
        ndTooltipTrigger
        variant="ghost"
        size="icon"
        aria-label="Dismiss notification"
      >
        <svg ndIcon="x"></svg>
      </button>
      <ng-template ndTooltipPortal>
        <div ndTooltipContent side="end">Dismiss</div>
      </ng-template>
    </ng-container>
  `,
})
export class TooltipIconButtonExample {}

Tooltip sides

Tooltips on each side of their triggers.

import { Component } from '@angular/core';
import type { NdSide } from '@ndop/primitives/tooltip';
import { Button } from '@/ui/button/button';
import {
  Tooltip,
  TooltipPortal,
  TooltipTrigger,
  TooltipContent,
} from '@/ui/tooltip/tooltip';

/**
 * Tooltips on each side of their triggers. `start` and `end` follow the
 * reading direction, so they swap in right-to-left layouts.
 */
@Component({
  selector: 'example-tooltip-sides',
  imports: [Button, Tooltip, TooltipPortal, TooltipTrigger, TooltipContent],
  template: `
    <div class="flex flex-wrap gap-2">
      @for (side of sides; track side) {
        <ng-container ndTooltip>
          <button ndButton ndTooltipTrigger variant="outline">
            {{ side }}
          </button>
          <ng-template ndTooltipPortal>
            <div ndTooltipContent [side]="side">On the {{ side }} side</div>
          </ng-template>
        </ng-container>
      }
    </div>
  `,
})
export class TooltipSidesExample {
  protected readonly sides: NdSide[] = ['top', 'end', 'bottom', 'start'];
}

Accessibility

Implements the Tooltip pattern of the WAI-ARIA Authoring Practices.

Keyboard

Keys the component handles.

Key Action
TabFocusing the trigger shows the tooltip; moving focus away hides it.
EscapeHides the tooltip without moving focus.

Focus

  • The tooltip never takes focus; focus stays on the trigger.

Right-to-left

As in Popover's spec.md: start and end sides and alignments swap in RTL.

API reference

Tooltip

[ndTooltip]

A tooltip (@ndop/primitives/tooltip): a short description of its trigger, shown after a delay on hover and at once on keyboard focus. Put it on an ng-container.

Tooltip binding Type Default
[defaultOpen]
Initial open state when open is not bound.
booleanfalse
[openDelay]
Delay before opening on hover, in milliseconds.
number700
[closeDelay]
Delay before closing once the pointer has left, in milliseconds.
number300
[(open)]
Whether the tooltip is open. Two-way bindable with [(open)].
booleanfalse

TooltipTrigger

[ndTooltipTrigger]

The element its tooltip describes, which shows it on hover and focus.

Manages aria-describedby.

Data attribute Values
data-slottooltip-trigger
data-state —

TooltipPortal

ng-template[ndTooltipPortal]

Marks the ng-template its tooltip renders while open.

TooltipContent

[ndTooltipContent]role tooltip

The tooltip bubble.

TooltipContent binding Type Default
[class]
Extra classes, merged last so they win.
string''
[side]
Preferred side of the trigger; start and end swap in RTL. Defaults to top, as in Radix and shadcn.
'bottom' | 'top' | 'start' | 'end''top'
[align]
Preferred alignment along that side.
'start' | 'end' | 'center''center'
[sideOffset]
Gap from the trigger, in pixels.
number4
Data attribute Values
data-slottooltip-content
data-state —
data-side —
data-align —

Agent notes

Do

  • Use tooltips for brief, supplementary text, such as the name of an icon-only button that also has an aria-label.
  • Keep the text to a few words.

Don't

  • Don't put essential information only in a tooltip; touch devices can't hover.
  • Don't put interactive content in a tooltip; use a popover.
  • Don't add a tooltip to a disabled button; it can't receive focus.