Tooltip
Hover and focus tooltip. Wrap a trigger in the default slot and set text. It shows after delay ms (default 200) and hides on leave or blur.
Preview
<esa-tooltip text="Tooltip above" position="above">
<button>Hover me</button>
</esa-tooltip> import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@esa/ecology/esa-tooltip';
@Component({
selector: 'app-tooltip-demo',
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<esa-tooltip text="Tooltip above" position="above">
<button>Hover me</button>
</esa-tooltip>
`,
})
export class TooltipDemo {} Positions
<esa-tooltip text="Tooltip above" position="above">…</esa-tooltip>
<esa-tooltip text="Tooltip below" position="below">…</esa-tooltip>
<esa-tooltip text="Left side" position="left">…</esa-tooltip>
<esa-tooltip text="Right side" position="right">…</esa-tooltip> import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@esa/ecology/esa-tooltip';
@Component({
selector: 'app-tooltip-demo',
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<esa-tooltip text="Tooltip above" position="above">…</esa-tooltip>
<esa-tooltip text="Tooltip below" position="below">…</esa-tooltip>
<esa-tooltip text="Left side" position="left">…</esa-tooltip>
<esa-tooltip text="Right side" position="right">…</esa-tooltip>
`,
})
export class TooltipDemo {} Focusable trigger
Any focusable element works — the tooltip shows on focusin as well as hover, so keyboard users get it too.
<esa-tooltip text="Shows on focus too" position="above">
<a href="#">Tab to me</a>
</esa-tooltip> import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@esa/ecology/esa-tooltip';
@Component({
selector: 'app-tooltip-demo',
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<esa-tooltip text="Shows on focus too" position="above">
<a href="#">Tab to me</a>
</esa-tooltip>
`,
})
export class TooltipDemo {} API
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | '' | Tooltip label. The tooltip does not render when empty. |
position | 'above' | 'below' | 'left' | 'right' | 'above' | Side the tooltip appears on. |
align | 'center' | 'start' | 'end' | 'center' | |
delay | number | 200 | Milliseconds to wait before showing on hover/focus. |
open | boolean | false | Reflected open state. |
Accessibility
- The bubble is
role="tooltip"and ispointer-events: noneso it never intercepts clicks. - Shows on both hover and focus, so keyboard users see the same hint as pointer users.
- Tooltips supplement — they should not be the only place critical information lives.
Theming surface
Every public token this component reads, extracted from its source at build time,
split by blast radius: the hooks that belong to this component,
then the shared and system tokens it consumes alongside everything else. The
Resolves to column walks each token's real lineage —
component → semantic → primitive → raw value — so you
can see exactly where re-pointing it lands. A spoke re-skins by overriding these in
its theme-<slug>.css; component internals are never edited. No
hook for what you need? File it with /request-lego.
Type roles it names
This component does not set a size, weight, face or tracking of its own — it names a composite, and the composite carries all five. A composite is a class rather than a token, so none of it appears in the tables below; re-theme text by re-pointing the token family, not by editing the component.
| Role | Re-point | Reach |
|---|---|---|
.typography-label-md |
| +33 more componentsesa-app-bar, esa-breadcrumbs, esa-button-group, esa-button-toggle, esa-card, esa-checkbox-group, esa-color-picker, esa-combobox, esa-command-palette, esa-confirm-dialog, esa-danger-zone, esa-date-picker, esa-dialog, esa-empty-state, esa-entity-search, esa-file-upload, esa-filter-container, esa-form-field, esa-header-nav, esa-input-tag, esa-link-column, esa-page-header, esa-pillbox, esa-popover, esa-progress-bar, esa-radio-group, esa-range-slider, esa-select, esa-side-dialog, esa-sidebar-nav, esa-stat, esa-text-field, esa-textarea |
.typography-microcopy-xs-subtle |
| +7 more componentsesa-combobox, esa-date-picker, esa-filter-dropdown, esa-filter-pills, esa-input-tag, esa-select, esa-text-field |
Wired to this component
No other component reads these — re-point them and esa-tooltip is the
only thing that moves.
| Token | Tier | Resolves to |
|---|---|---|
--tooltip-max-width | component | 240px |
Shared tokens it reads
Owned by a family or by the semantic layer. Still overridable — but scope the
override (esa-foo { --form-border-color: … }) unless you mean to move
everything that reads it. Reach says what else that is.
| Token | Reach | Resolves to |
|---|---|---|
--animation-enter | semantic every component | 150ms via --duration-150 |
--color-background-default-knockout | semantic every component | #202020 via --color-gray-12 |
--color-content-default-knockout | semantic every component | #fcfcfc via --color-gray-1 |
--elevation-4 | semantic every component | 0 via --shadow-offset-x |
--radius-sm | semantic every component | 0.25rem via --radius-100 |
--z-tooltip | semantic every component | 600 |
--spacing-150 | primitive every component | 0.375rem |
--spacing-250 | primitive every component | 0.625rem |