Tooltip
A short label that appears on hover or focus. It is the component most likely to be handed information it must not hold, because it is the easiest place to put something when a layout is full.
Overview
This system bans hover as a sole carrier of information — see Interaction states — which puts the tooltip in an awkward position. The resolution is not to forbid it, but to be exact about what it is for: a tooltip supplements something already visible. It never carries anything a clinician needs in order to act.
Roughly half the surfaces this system targets are touch-only, where hover does not exist at all. A tooltip on a cart display is not a degraded experience — it is nothing. Anything that would be lost there was never safe to put in a tooltip.
Supplementary
Removing every tooltip in the product must change nothing about what a clinician can do or decide. If it does, that content belongs on the page.
Reachable
Hover, keyboard focus and long-press all open it. A tooltip only a mouse can reach is unavailable to most of the people using it.
Brief
A few words naming a thing. A tooltip containing a sentence is a popover; one containing a decision is a defect.
Anatomy
Both bubbles are shown open so they can be read here. In use they appear on hover, focus or long-press, one at a time.
| Element | Rule |
|---|---|
| Trigger | An interactive control, or an <abbr>. Never a bare span — a
tooltip on something unfocusable is unreachable by keyboard. |
| Bubble | Inverse surface, one line where possible, 200 px maximum when wrapping. |
| Relationship | aria-describedby. The control still carries its own accessible name via
aria-label — the tooltip does not supply it. |
An icon-only button needs both an aria-label (so assistive
technology and voice control can name it) and a tooltip (so a sighted user can
discover what the glyph means). Using the tooltip as the label leaves the control unnamed for
anyone not hovering it; using the label alone leaves a sighted clinician guessing at an icon
under time pressure.
What must never go in a tooltip
| Never | Because | Instead |
|---|---|---|
| Units of a measurement | The value becomes unitless on touch and in print | Permanent suffix or label — Text field |
| A confidence score | Reliance information must be visible at the moment of the decision | Confidence disclosure |
| Patient identifiers | Identity is never conditional on a pointer | Patient header |
| An error or validation message | Errors must persist and be announced | Inline error text with aria-describedby |
| The full text of a truncated clinical value | Truncation of clinical content is itself prohibited | Wrap, reflow, or shorten the label |
| Anything needed to choose between two actions | Decisions are not made by hovering | Visible helper text, or a Dialog |
What a tooltip is legitimately for
- Naming an icon-only control, alongside its
aria-label. - Expanding an abbreviation on first use in an interface — ACS, LBBB, GSPR.
- Restating a non-clinical label that has been shortened for a dense column header, where the full text is available elsewhere.
- Naming a keyboard shortcut for an action that is already visible.
Why "nothing crucial" is not a usable rule
Almost every design system states some version of never put crucial information in a tooltip. It is correct, and it does not work — because "crucial" is undecidable at design time and everybody believes their case is the exception.
The usual evidence is on the same pages that state it. A widely-used system publishes the rule and then recommends tooltips for truncated text, for defining terms, for alternative text on images, and for the values behind a chart. Each of those is defensible in isolation. Together they are four routes to putting something load-bearing behind a pointer, on a page whose own rule forbids exactly that.
Remove every tooltip in the product. Does anything change about what a clinician can do or decide? If yes, that content belongs on the page. The question has one answer, it can be asked of a design before it is built, and it does not depend on anyone's judgement about importance.
The four that look reasonable
Revealing truncated text
The most common recommendation and the one this system has least room for, because truncating clinical content is itself prohibited. A tooltip here is a second defect covering for a first: the text is clipped, and the only complete copy is behind a pointer that half our surfaces do not have. Wrap, widen, or shorten the label.
Defining a term
Legitimate for an abbreviation whose expansion is a convenience — "ACS" for a reader who already knows what it stands for. Not legitimate for a definition the reader needs in order to act, which is most definitions worth writing. The test above settles it: if removing the tooltip changes what they can decide, the expansion belongs in the text on first use.
Alternative text for an image
This one is not a judgement call — it is simply wrong. A tooltip is not alternative
text. Assistive technology reads the alt attribute; a
title or a hover bubble is not a substitute and is inconsistently announced. An
image whose description lives in a tooltip has no description for the reader who most needs
one, and the recommendation inverts the accessibility it appears to serve.
The values behind a chart
The most defensible of the four, which makes it the most dangerous. Hover-to-read is the near-universal convention for charts, and it puts the numbers — the actual data — behind a pointer.
- A chart's values are readable without hovering. Direct labelling on the points that matter, or an accompanying table, per Data visualisation. A trend a clinician cannot read without a mouse is a trend they cannot read on a cart.
- A hover readout is an accelerator over a readable representation, never the route to the numbers — the distinction Affordance draws between an accelerator and the only path.
- On touch, inspecting a point is a tap, and the value stays until dismissed or another point is chosen. A readout that vanishes when the finger lifts has been read by nobody.
- The precision on hover matches the precision printed. A chart whose tooltip reveals two decimal places the axis does not show is offering a precision the rendering never claimed, and the reader will quote it.
Each begins with a real layout problem — text too long, a term unfamiliar, an image without words, a chart too dense to label. The tooltip solves the layout problem and moves the information somewhere half the readers cannot reach. It is a container that makes a design look finished without being finished, which is why it is the component most often handed things it must not hold.
Behaviour
WCAG 2.2 SC 1.4.13 sets three requirements for content shown on hover or focus, and all three are met by the component rather than by each call site.
| Requirement | Implementation |
|---|---|
| Dismissible | Esc closes without moving the pointer or focus. |
| Hoverable | The pointer can travel into the bubble without it closing — so a magnified user can reach content that overlaps their cursor. |
| Persistent | Stays until dismissed, focus moves, or the pointer leaves. Never auto-hides on a timer. |
- Open delay 400 ms, close delay 0. Long enough that a pointer crossing the screen does not trail bubbles; instant on exit so nothing is left obscuring content.
- No delay when the trigger receives keyboard focus. A keyboard user asked for it explicitly.
- Long-press opens on touch, and dismisses on the next tap anywhere.
- Never covers its own trigger, and never covers an active alarm — a tooltip yields position rather than overlapping the alert region.
- One at a time. Tooltips never stack or chain.
Writing it
- One to four words for a control name; one short clause for an abbreviation.
- Name the action, not the icon. "Compare with prior ECG", never "Arrows".
- No full stop, sentence case, no "Click to…".
- Never duplicate visible text. A tooltip on a labelled button is noise that obscures the row beneath it.
Names the action. The button is independently labelled, so nothing is lost on a touch display.
Unit, confidence and model version behind a hover. On a cart display this is the number 47, unqualified, in a clinical record.
What the component enforces, and what it only asks for
All three of the WCAG 1.4.13 behaviours are held here, which was not true until a browser was pointed at them. What is not held is whether the tooltip should exist at all.
| Rule | Held by | How |
|---|---|---|
| Dismissible without moving the pointer | The component | Escape closes it — one of three behaviours this page claimed and none of which existed before the interaction gate. Asserted: Tooltip: Escape dismisses it — SC 1.4.13, dismissible |
| Hoverable | The component | The pointer handlers are on the wrapper, so moving onto the tooltip does not dismiss it. Asserted: Tooltip: the bubble is hoverable — SC 1.4.13 |
| Persistent while hovered or focused | The component | No timeout. It closes when the pointer or focus leaves, and not before. Asserted: Tooltip: stays open while hovered, with no timeout of its own |
| Opens on focus without the hover delay | The component | 400 ms on hover, immediate on focus, so a keyboard user is not made to wait. Asserted: Tooltip: opens after a delay on hover, instantly on focus |
| It adds to a control’s description rather than replacing it | The component | The tip’s id is appended to the control’s own aria-describedby, and the control’s own focus handlers still run. It replaced both: wrapping a field in a tooltip deleted its hint, and while the tip was closed deleted it entirely. Read from the accessibility tree.Asserted: Tooltip: it adds to a control's description, and keeps the control's own |
| It never carries the name of its control | You | content is a string. A tooltip repeating the accessible name is invisible to the reader who most needs it, and only you can see that you have done it. |
| Nothing clinical lives only here | You | A tooltip is supplementary by rule, not by construction. Nothing stops you putting a reference range in one, where no touch user will find it. |
A rule stated on a component page reads as a rule the component keeps. 4 of these 6 are; 2 are obligations this page was quietly handing to the reader. Conformance is held; editorial judgement is not. A tooltip that duplicates its label passes every check on this page and helps nobody.
Do's and don'ts
Tooltip and aria-label both present. Nothing is lost on a touch display.
The tooltip used as the accessible name. Voice control and screen readers have nothing to call this button.
14 → 47 → 112
14:26 · 15:26 ·
16:26
The values are on the page. A hover readout may sit on top of this as an accelerator; it is not how the numbers are reached.
A line, three unlabelled points.
The data is behind a pointer. On a cart the trend has a shape and no numbers, and nobody can quote it.
Acute coronary syndrome (ACS) was not excluded by the 0/1 h algorithm.
Expanded on first use, in the text. The reader needs it to follow the sentence, so it is in the sentence.
ACS was not excluded by the 0/1 h algorithm.
The expansion is available to a reader with a pointer who thinks to hover. Everyone else reads three letters.
<img alt="12-lead ECG, anterior ST elevation in V2–V4">
The description is in the attribute assistive technology reads.
<img title="12-lead ECG, anterior ST elevation in V2–V4">
A tooltip is not alternative text. The image now has no description for the reader who most needs one, and the recommendation inverts the accessibility it appears to serve.
Accessibility
- Trigger must be focusable. Buttons, links and
<abbr>withtabindexwhere it carries a tooltip. aria-describedby, notaria-labelledby. The tooltip describes; the control's own label names.- Never use the
titleattribute. It is unreachable by keyboard, inconsistently announced, cannot be styled, and cannot meet SC 1.4.13. - Contrast. The inverse surface meets AA in both themes — the same computed pairs as Colour.
- Reduced motion removes the fade; it never removes the tooltip.
- Zoom. At 200 % the bubble reflows and repositions inside the viewport rather than clipping.
Outcomes of use
What this contributes to, in the terms of Usability & context of use. These are attributes believed to contribute to an outcome; the outcome itself is settled by observing real use in a specified context, not by this page.
- Effectiveness — icon meaning learned without guessing. Since nothing decision-relevant lives here, a tooltip that never appears cannot cause an error.
- Efficiency — removes the hesitation an unlabelled glyph produces, without spending the space a permanent label would.
- Satisfaction — reduces the low-grade uncertainty of an unfamiliar toolbar, which is most of what makes a first shift with a new tool unpleasant.
Clinical safety notes
Trace these in your risk file (ISO 14971) and usability engineering file (IEC 62366-1). Which of these the component keeps and which are yours is stated in the guarantees table; a control the component does not keep is one your risk file must show you keep.
- Never the sole carrier of anything. (you) Mitigates: information silently absent on touch surfaces, in print, and for keyboard users who never trigger it.
- Never holds units, identifiers, confidence or errors. (you) Mitigates: a clinical value read without the qualifier that makes it meaningful.
- Not the accessible name. (the component describes, never names; giving the control a name is you) Mitigates: icon-only controls being unnamed for assistive technology and voice control.
- Dismissible, hoverable, persistent. (the component) Mitigates: a bubble obscuring content a magnified user cannot get out from under.
- Never overlaps the alert region. (you) Mitigates: a hover artefact hiding an active alarm.
- No
titleattribute anywhere. (the component; nothing here sets one) Mitigates: content that appears to be provided and is not reachable.
Implementation
$ npx shadcn@latest add https://md.notjustany.tech/r/tooltip.json
<Tooltip content="Opens the prior study alongside this one">
<Button variant="outline">Compare with prior</Button>
</Tooltip>
// The trigger is a labelled button, not an icon: this package has no icon
// set, and a tooltip may not carry the name of the control it sits on.
// Hover opens after 400 ms, focus opens at once, Escape closes, and the
// surface is hoverable — SC 1.4.13.
What the component takes. This table used to list openDelay, side — props the component does not have, and never had. Found by the registry gate’s props-table rule.
| Prop | Type | Default | Notes |
|---|---|---|---|
content | string | — | Plain text only. Rich content means you wanted a Dialog or popover. |
children | React.ReactElement | — | Required. The control it describes. Its own name and description are kept. |
Related
- Affordance & perceivability — the general rule this page applies: a control exists only if every reader who can operate it can perceive it.
- Interaction states — why hover carries nothing.
- Button — icon-only controls and their labels.
- Dialog — when content is a decision, not a label.
- Accessibility — SC 1.4.13 in context.