Flux 2.0

Component

Tooltip and popover

A short label on hover or focus, and a small panel opened by a button.

Plain-text source, for agents and clipboard use: /components/source/tooltip.txt

When to use it

A tooltip names an icon-only control or adds a few words about it, on hover and on focus. A popover is a small panel anchored to its button, for a short task that should not leave the page: a confirmation with one choice, a quick setting. Both sit in the top layer, so no scroll container clips them, and both are placed beside their trigger by the script.

Not this
Not for explanation of a form field; that is the Input’s info bubble. Not for a list of actions; that is a menu. Not for anything with more than a couple of fields, or that needs the page to wait; that is a Modal. Not for content on something that cannot take focus, such as plain text.

Examples

Tooltips on icon-only buttons

The tooltip is the button’s name, so the button references it with aria-labelledby.

Export as CSV Print manifest
html
<button class="flux-button flux-button--ghost flux-button--sm" type="button" aria-labelledby="tip-export" data-flux-tooltip="tip-export"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 2.5v7.5M5 7l3 3 3-3M3 12.5h10" /></svg></button>
<span class="flux-tooltip" id="tip-export" role="tooltip" popover="manual">Export as CSV</span>
<button class="flux-button flux-button--ghost flux-button--sm" type="button" aria-labelledby="tip-print" data-flux-tooltip="tip-print"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4.5 6V2.5h7V6M4.5 11h-2V6h11v5h-2M4.5 9h7v4.5h-7z" /></svg></button>
<span class="flux-tooltip" id="tip-print" role="tooltip" popover="manual">Print manifest</span>

Popover

A short confirmation anchored to its button. Light dismiss, Escape and returning focus come from the platform.

html
<button class="flux-button flux-button--secondary" type="button" popovertarget="pop-hold" aria-haspopup="dialog" aria-expanded="false">Hold seats</button>
<div class="flux-popover" id="pop-hold" popover role="dialog" aria-labelledby="pop-hold-title">
  <h3 class="flux-popover__title" id="pop-hold-title">Hold 4 seats?</h3>
  <p class="flux-popover__body">The seats are held for 48 hours, then released to sale.</p>
  <div class="flux-popover__actions">
    <button class="flux-button flux-button--ghost flux-button--sm" type="button" popovertarget="pop-hold" popovertargetaction="hide">Cancel</button>
    <button class="flux-button flux-button--sm" type="button">Hold seats</button>
  </div>
</div>

Anatomy

PartDescription
TooltipA manual popover with role="tooltip": text-inverse on surface-inverse, one line where possible.
TriggerA focusable control with data-flux-tooltip naming the tooltip’s id.
PopoverA panel on surface-raised with a hairline and --flux-popover-shadow, opened with popovertarget.
Popover partsAn optional title, a body in text-secondary, and actions aligned to the end.

API

NameKindDescription
flux-tooltipclassOn an element with role="tooltip", an id and popover="manual".
data-flux-tooltipattributeOn the trigger: the tooltip’s id. Opens it on hover and focus. Requires flux-components.js.
aria-labelledby / aria-describedbyattributelabelledby when the tooltip is the control’s name, describedby when it adds to a visible label.
flux-popoverclassOn an element with popover, an id and role="dialog", opened by a button with popovertarget.
flux-popover__titleclassOptional heading, referenced by aria-labelledby.
flux-popover__bodyclassThe text of the popover.
flux-popover__actionsclassButtons, end-aligned. popovertargetaction="hide" closes without script.

States

StateTreatment
Tooltip openAbove the trigger, or below when there is no room; stays open while the pointer is over it.
Popover openBelow the trigger, aligned to its end, flipped above when there is no room. aria-expanded follows.

Keyboard

KeysAction
TabFocusing a trigger opens its tooltip; leaving it closes it.
Enter / SpaceOpens or closes a popover. Focus moves to its first control.
EscapeCloses the tooltip or the popover; a popover returns focus to its button.

Accessibility

  • A tooltip opens on focus as well as hover, stays while the pointer is over it, and closes on Escape, as WCAG 1.4.13 requires.
  • A tooltip holds text only. Anything interactive belongs in a popover.
  • An icon-only button takes its name from its tooltip with aria-labelledby, so the name exists even when the tooltip is closed.
  • Give a popover role="dialog" and a name, and keep it short enough that its controls are reached with a few Tabs.

Tokens

The tier-3 and tier-2 tokens this component binds to. Change the token, not the component.

  • --flux-tooltip-bg | -text | -radius | -font-size | -padding-x | -padding-y | -max-width | -offset
  • --flux-popover-width | -padding | -gap | -bg | -border | -shadow | -radius

Do and don’t

Do

  • Keep a tooltip to a few words: what the control does.
  • Use a popover for one decision about the thing its button is on.

Don’t

  • Do not put the only copy of important information in a tooltip. It is invisible until someone looks for it.
  • Do not open a popover on hover.
  • Do not stack a popover on a popover.