Atomic Angular — Doc interne

Tooltip

A short description shown next to any element on hover and keyboard focus, placed in the top layer — the galactik replacement of the @sinequa/ui tooltip directive.

TooltipDirective ([tooltip]) shows a short text, or a template, next to the element it sits on. It opens on hover and on keyboard focus, closes on Escape, on blur and on scroll, and lets the pointer move onto the tooltip without closing it.

Concept — a tooltip describes, it does not name

The host gets aria-describedby pointing at the tooltip while it is open. A screen reader reads the description after the element's own name, so an icon-only button still needs an aria-label: the tooltip is never its accessible name. Keep the text short — anything the user must read or interact with belongs in a Popover or a Dialog.

Minimal example

A tooltip on a button
sample.component.ts
import { Component } from "@angular/core";
import { TooltipDirective } from "@sinequa/galactik";

@Component({
  selector: "sample-component",
  imports: [TooltipDirective],
  template: `
    <button type="button" aria-label="Delete" tooltip="Delete this item" tooltipPosition="top">Delete</button>
  `,
})
export class SampleComponent {}

How it works

mouseenter or keyboard focus event, after showDelay createComponent, appended to body injectFloatingPanel, top layer, autoUpdate, flip, shift aria-describedby gets the panel id Escape, blur, scroll, press, or the pointer leaves destroy, listeners and aria-describedby removed User Host with tooltip TooltipDirective tooltip-panel

The panel is a role="tooltip" element created on demand — inside the closest <dialog> or [popover] when the host is in one (a modal dialog makes everything outside it inert, and a popover closes on a click outside of it: left on body, the tooltip could no longer be hovered or clicked), in body otherwise — and positioned by injectFloatingPanel as a manual popover: it renders in the top layer, above a <dialog> and outside the clipping of any ancestor, with no z-index. Nothing listens on the document while the tooltip is closed — the Escape and scroll listeners are added when it opens and removed when it closes.

A press on the host (pointerdown, click) closes the tooltip, and the focus that a press gives a button does not open it again: only a keyboard focus does.

Recipes

A template as the content

Pass a TemplateRef, or declare an <ng-template tooltip-content> inside the host.

A tooltip with a template
sample.component.ts
import { Component } from "@angular/core";
import { KbdComponent, TooltipContentDirective, TooltipDirective } from "@sinequa/galactik";

@Component({
  selector: "sample-component",
  imports: [KbdComponent, TooltipContentDirective, TooltipDirective],
  template: `
    <button type="button" [tooltip]="help">Search</button>
    <ng-template #help>Press <kbd>Ctrl</kbd> + <kbd>K</kbd></ng-template>

    <button type="button" tooltip>
      Filters
      <ng-template tooltip-content><em>Narrow the results</em></ng-template>
    </button>
  `,
})
export class SampleComponent {}

Delays, lifetime, and which event opens it

Delays and events
sample.component.ts
import { Component } from "@angular/core";
import { TooltipDirective } from "@sinequa/galactik";

@Component({
  selector: "sample-component",
  imports: [TooltipDirective],
  template: `
    <button type="button" tooltip="Opens after 800 ms" [showDelay]="800">Slow</button>
    <button type="button" tooltip="Gone after 2 s" [life]="2000">Short-lived</button>
    <button type="button" tooltip="Closes the moment you leave" [autoHide]="false">Strict</button>
    <button type="button" tooltip="Keyboard focus only" tooltipEvent="focus">Focus</button>
  `,
})
export class SampleComponent {}

Everything in one object

[tooltipOptions] takes the same settings as the inputs. An input set on its own wins over the object.

tooltipOptions
sample.component.ts
import { Component } from "@angular/core";
import { TooltipDirective, type TooltipOptions } from "@sinequa/galactik";

@Component({
  selector: "sample-component",
  imports: [TooltipDirective],
  template: `<button type="button" tooltip [tooltipOptions]="options">Save</button>`,
})
export class SampleComponent {
  protected readonly options: TooltipOptions = {
    tooltipLabel: "Saves the document",
    tooltipPosition: "right",
    showDelay: 300,
  };
}

Driving it from code

exportAs="tooltip" gives the instance: show(), hide() and the isOpen signal.

Show and hide from code
sample.component.ts
import { Component } from "@angular/core";
import { TooltipDirective } from "@sinequa/galactik";

@Component({
  selector: "sample-component",
  imports: [TooltipDirective],
  template: `
    <button type="button" tooltip="Copied" #copied="tooltip" (click)="copied.show()">Copy</button>
  `,
})
export class SampleComponent {}

Options

Prop

Type

The tooltip's width is capped by the --tooltip-max-w custom property (default 20rem); set it on the host or on an ancestor.

Migration from @sinequa/ui

The selector is the same, so a consumer moves with an import change — and cannot use both directives in one template. What changed, and why:

@sinequa/ui@sinequa/galactik
Hover onlyHover and keyboard focus (tooltipEvent), Escape closes it
No ARIArole="tooltip" and aria-describedby while open
tooltip-positiontooltipPosition (the old name still works)
tooltip-delay (delay before hiding)hideDelay (the old name still works)
tooltip-offsettooltipOffset (the old name still works)
tooltip-duration, default 3000life, default 0 — a tooltip no longer closes by itself (the old name still works)
No arrowAn arrow by default ([tooltipArrow]="false" removes it)
[strategy]Removed: always fixed, in the top layer
.tooltip class styled by the applicationStyled by the library, from galactik tokens
Appended to the closest <dialog> or bodyAlways in the top layer, above dialogs
document scroll listener never removedListeners live only while the tooltip is open

Pitfalls

What's next

On this page