Primitive
Tooltip
Hover + focus-triggered floating label. Uses native popover API when available, falls back to positioned div. Supports rich slotted content for footnote-style previews (Week-4 dependency).
1. Simple label
Hover or focus the Tooltip activates after a 400ms hover delay or immediately on focus. to see the default tooltip.
<Tooltip content="Tooltip activates after a 400ms hover delay or immediately on focus.">
<button type="button">trigger</button>
</Tooltip> 2. Placement options
<Tooltip content="Top placement (default)" placement="top"> <button>Top</button> </Tooltip>
<Tooltip content="Bottom placement" placement="bottom"> <button>Bottom</button> </Tooltip>
<Tooltip content="Left placement" placement="left"> <button>Left</button> </Tooltip>
<Tooltip content="Right placement" placement="right"> <button>Right</button> </Tooltip> 3. Footnote-preview (rich slot)
Speech datasets collected without explicit consent fail Article 10 [1] EU AI Act, Article 10(3)
Training, validation and testing data sets shall be relevant, sufficiently representative, and to the best extent possible, free of errors and complete in view of the intended purpose.
Regulation (EU) 2024/1689
<Tooltip placement="top" maxWidth="360px" delay={250}>
<a href="#fn1">[1]</a>
<Fragment slot="content">
<strong>EU AI Act, Article 10(3)</strong>
<p>Training, validation and testing data sets shall be relevantβ¦</p>
<p>Regulation (EU) 2024/1689</p>
</Fragment>
</Tooltip> 4. Custom delay
Need an instant tooltip? Set No delay β appears immediately on hover. for instant feedback (good for sparse, frequent UI).
<Tooltip content="No delay β appears immediately on hover." delay={0}>
<button type="button">Instant</button>
</Tooltip> 5. Inline-link wrapper
Read about YPAI Yourpersonal.AI is an EU-resident AI training-data company building speech corpora for high-risk pipelines. and its compliance focus.
<Tooltip content="Yourpersonal.AI is an EU-resident AI training-data companyβ¦">
<a href="/about">YPAI</a>
</Tooltip> Anatomy
| Property | Behavior |
|---|---|
| Trigger | The slotted element. Picks up `aria-describedby` pointing to the popover. |
| Popover | Native `<div popover>` when available; falls back to absolutely-positioned div. |
| Arrow | CSS pseudo-element on the popover; placement-aware. |
| Content slot | Either the `content` prop (text) or the `slot="content"` (rich HTML). |
Accessibility
- Trigger receives
aria-describedbypointing at the popover; SR announce the tooltip text after the trigger's name. - Tooltip opens on both hover AND focus β keyboard users see it without a mouse.
- Focus opens the tooltip immediately (no
delay) so keyboard nav never feels laggy. - Escape dismisses the tooltip and returns focus to the trigger.
- Tooltip content is never interactive β clicks pass through to the trigger if the popover is dismissed first.
- Hidden under
prefers-reduced-motionthe fade transition collapses to 0.01ms.
Do / Don't
| Property | Do | Don't |
|---|---|---|
| Content length | Keep tooltip text under ~120 characters; one sentence max. | Cram a paragraph in β use a Popover or in-place text once Popover ships. |
| Interactivity | Use Tooltip for read-only label / preview content. | Put buttons or links inside Tooltip β they cannot be reached on touch devices. |
| Touch parity | Pair tooltip content with a visible label whenever possible. | Hide critical information behind hover only β touch users will never see it. |
| Delay | Keep the default 400ms; bump to 0ms only for frequent / sparse UI. | Use long delays (>800ms) β users assume the UI is dead. |
| Placement | Let the default ("top") choose; flip manually only when blocking content. | Force "left" or "right" without testing RTL β mirror behaviour is built in. |
Props
| Property | Type | Default | Notes |
|---|---|---|---|
| content | string | - | Plain-text label; use slot="content" for rich |
| placement | "top" | "bottom" | "left" | "right" | "top" | - |
| delay | number (ms) | 400 | Hover-show delay; focus is immediate |
| maxWidth | CSS length | "280px" | Bump to 360px+ for previews |
| className | string | "" | Extra wrapper classes |
Source
<!-- Simple label -->
<Tooltip content="Activates after 400ms hover">
<button>Hover me</button>
</Tooltip>
<!-- Rich slotted preview (footnote pattern) -->
<Tooltip placement="top" maxWidth="360px">
<a href="#fn1">[1]</a>
<Fragment slot="content">
<strong>Source title</strong>
<p>Longer-form excerpt body, supports multi-paragraph content.</p>
</Fragment>
</Tooltip>