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
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
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.
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
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.
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.
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 only | Hover and keyboard focus (tooltipEvent), Escape closes it |
| No ARIA | role="tooltip" and aria-describedby while open |
tooltip-position | tooltipPosition (the old name still works) |
tooltip-delay (delay before hiding) | hideDelay (the old name still works) |
tooltip-offset | tooltipOffset (the old name still works) |
tooltip-duration, default 3000 | life, default 0 — a tooltip no longer closes by itself (the old name still works) |
| No arrow | An arrow by default ([tooltipArrow]="false" removes it) |
[strategy] | Removed: always fixed, in the top layer |
.tooltip class styled by the application | Styled by the library, from galactik tokens |
Appended to the closest <dialog> or body | Always in the top layer, above dialogs |
document scroll listener never removed | Listeners live only while the tooltip is open |
Pitfalls
What's next
Floating panel
injectFloatingPanel keeps a popup — a combobox's list, a submenu — under or beside an anchor with Floating UI, as wide as the anchor on request and in the top layer above a dialog.
Layout
Panel layout — ResizablePanelGroup, ResizablePanel, ResizableHandle — for user-resizable panel arrangements.