A short hint shown on hover and keyboard focus, anchored to its trigger in the top layer with hover intent.

Last updated

Uses JavaScript

Opens the bubble in the top layer with hover intent (120 ms on first hover, instant for neighbours), opens on focus at once, closes on Escape, ignores touch pointers, and moves aria-describedby onto the focusable trigger.

Without JS: A CSS-only bubble above the trigger on hover and focus; no delay, and an overflow ancestor can clip it.

Copy to clipboard
Show code
<Tooltip text="Copy to clipboard">
<Button variant="outline" color="neutral">Copy</Button>
</Tooltip>

Add

npx @ava-ui/apogee add tooltip

Depends on utils (anchored-panel helper, island). No icons.

Usage

---
import Tooltip from '@/components/apogee/Tooltip/Tooltip.astro'
import Button from '@/components/apogee/Button/Button.astro'
---
<Tooltip text="Copy to clipboard" placement="bottom">
  <Button variant="outline" color="neutral">Copy</Button>
</Tooltip>

Anatomy

  • Trigger — whatever you put in the default slot. Make it focusable (a button or link) so keyboard users get the hint too; the island moves aria-describedby onto it.
  • Bubble — a role="tooltip" popover="manual" span anchored to the trigger, in the top layer.

API

@composable — exposed to Content Editors in AVA. Any other attribute passes through to the root wrapper <span>.

Prop Type Default Description
text string — The hint. Wraps at 20rem. An empty string renders the slot alone, no bubble.
description string — A second, muted line under the text; the bubble becomes left-aligned with more padding.
arrow boolean false A small triangle on the edge facing the trigger.
delay number 120 Hover delay before opening, in ms.
closeDelay number 150 Delay before closing after the pointer leaves, in ms.
placement 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'start' | 'start-top' | 'start-bottom' | 'end' | 'end-top' | 'end-bottom' 'top' Side and alignment; flips when out of room. start/end mirror in RTL.
panelClass string — Extra classes on the bubble.
class string — Extra classes on the root wrapper.

Slots: the default slot is the trigger; shortcut renders inline after the text (a Kbd).

Variants

EditDeleteDocsOpens in a new tab
Newest first by default
Show code
<Tooltip text="Edit"><Button variant="ghost" color="neutral" iconOnly aria-label="Edit">✎</Button></Tooltip>
<Tooltip text="Delete"><Button color="critical">Delete</Button></Tooltip>
<Tooltip text="Opens in a new tab"><a href="#" class="text-primary underline">Docs</a></Tooltip>
<Tooltip text="Newest first by default"><Select aria-label="Sort"><option>Newest</option><option>Oldest</option></Select></Tooltip>

Description, arrow and shortcut

Save draftKeeps the draft on this device until you publish.BoldSearch⌘KInstant
Show code
<Tooltip text="Save draft" description="Keeps the draft on this device until you publish.">
<Button variant="outline" color="neutral">Save</Button>
</Tooltip>
<Tooltip text="Bold" arrow><Button variant="outline" color="neutral">B</Button></Tooltip>
<Tooltip text="Search"><Kbd slot="shortcut">⌘K</Kbd><Button variant="outline" color="neutral">Search</Button></Tooltip>
<Tooltip text="Instant" delay={0}><Button variant="outline" color="neutral">No delay</Button></Tooltip>

Placement

All twelve values.

top-start
top
top-end
bottom-start
bottom
bottom-end
start-top
start
start-bottom
end-top
end
end-bottom
Show code
<Tooltip text="top-start" placement="top-start"><Button variant="outline" color="neutral">top-start</Button></Tooltip>
… one per value …

With an existing description

The island appends the bubble’s id to any aria-describedby the trigger already has, so a control keeps its other descriptions.

Deletes the draft; this cannot be undone.

Delete draft
Show code
<p id="tt-note">Deletes the draft; this cannot be undone.</p>
<Tooltip text="Delete draft">
<Button color="critical" iconOnly aria-label="Delete" aria-describedby="tt-note">✕</Button>
</Tooltip>

Long text and clipping

Text wraps at 20rem. The bubble is in the top layer, so an overflow: hidden ancestor cannot cut it off.

Exports every row that matches the current filters as a comma-separated file, including hidden columns.
Show code
<div class="w-56 overflow-hidden rounded-md border border-neutral p-4">
<Tooltip text="Exports every row that matches the current filters as a comma-separated file, including hidden columns.">
  <Button variant="outline" color="neutral">Export</Button>
</Tooltip>
</div>

States

  • Hidden (default) — the popover is closed.
  • Shown — after delay (120 ms) of hover (instantly when a neighbouring tooltip closed within the last 500 ms), or at once on focus; fades in and slides from the trigger’s side (--duration-fast, --ease-standard).
  • Closing — closeDelay (150 ms) after the pointer leaves, at once on blur or Escape.

Examples

An icon-only button is the classic case: the visible label is the tooltip, the accessible name is aria-label.

<Tooltip text="Settings">
  <Button variant="ghost" color="neutral" iconOnly aria-label="Settings"><Settings /></Button>
</Tooltip>

Accessibility

Key Action
Tab Focusing the trigger shows the tooltip; moving focus away hides it.
Esc Hides the tooltip without moving focus (WCAG 1.4.13).
  • The bubble has role="tooltip"; the focusable trigger points at it with aria-describedby, so screen readers read the hint after the trigger’s name (hidden popover content still counts as a description).
  • Appears on keyboard focus, not only hover. Put a focusable element in the slot or keyboard users never see it.
  • The hint is supplementary. Never put the only label of a control in a tooltip; give the control an accessible name of its own.
  • On touch, a tap shows it; it closes after 4 seconds or on a tap elsewhere.
  • The fade respects prefers-reduced-motion.

Tokens

Token Used for
--background-inverted Bubble background
--on-inverted Bubble text
--radius-md Corner radius
--duration-fast / --ease-standard Fade transition

Do / Don’t

  • Do use it for a two-to-five-word hint on icon buttons and truncated labels.
  • Do keep the trigger focusable.
  • Don’t put links, buttons or formatted text in it; the bubble is plain text and cannot be hovered.
  • Don’t rely on it on touch screens; use visible text or a Popover for anything essential.

Content

  • Sentence case, no ending period: “Copy to clipboard”, not “Copy to clipboard.”
  • Name the action or the outcome, not the control: “Opens in a new tab” rather than “Link”.