Tooltip
A tooltip is a headless component that displays brief, contextual information when made visible. It uses role="tooltip" for semantic identification and is designed to be linked to a trigger element via aria-describedby, providing supplementary text that screen readers can announce.
Tooltips are used to clarify the function or meaning of an element without cluttering the interface, offering helpful hints, labels, or explanations on demand. The consumer controls visibility through the bindable visible prop and is responsible for toggling it on hover, focus, or other interaction events.
Example
Show demo markup
<div class="tooltip" role="tooltip">Helpful tip text</div>
Usage example
<script lang="ts">
import Tooltip from "./Tooltip.svelte";
let show = $state(false);
</script>
<button
type="button"
aria-describedby="tip"
onmouseenter={() => (show = true)}
onmouseleave={() => (show = false)}
onfocus={() => (show = true)}
onblur={() => (show = false)}
>
Save
</button>
<Tooltip id="tip" label="Save your changes" bind:visible={show} />
Show Svelte source
// In your Svelte component:
import Tooltip from "lily-design-system-svelte-headless/components/Tooltip/Tooltip.svelte";
<Tooltip>
<!-- content -->
</Tooltip>
Usage
Tooltip on an icon button:
<button aria-describedby="save-tip"
onmouseenter={() => showSaveTip = true}
onmouseleave={() => showSaveTip = false}
onfocusin={() => showSaveTip = true}
onfocusout={() => showSaveTip = false}
>
<Icon name="save" />
<ScreenReaderSpan>Save document</ScreenReaderSpan>
</button>
<Tooltip id="save-tip" label="Save document" visible={showSaveTip} />
Tooltip explaining an abbreviation:
<span aria-describedby="a11y-tip"
onmouseenter={() => showA11yTip = true}
onmouseleave={() => showA11yTip = false}
onfocusin={() => showA11yTip = true}
onfocusout={() => showA11yTip = false}
tabindex="0"
>
WCAG
</span>
<Tooltip id="a11y-tip" label="Web Content Accessibility Guidelines" visible={showA11yTip} />
Tooltip for a toolbar action:
<button aria-describedby="delete-tip"
onmouseenter={() => showDeleteTip = true}
onmouseleave={() => showDeleteTip = false}
onfocusin={() => showDeleteTip = true}
onfocusout={() => showDeleteTip = false}
>
<Icon name="trash" />
</button>
<Tooltip id="delete-tip" label="Delete selected items" visible={showDeleteTip} />
Props
label: string (required) -- the tooltip text content
visible: boolean (default: false) -- bindable boolean controlling whether the tooltip is shown
id: string (default: undefined) -- optional id for linking to a trigger element via aria-describedby
...restProps: unknown -- additional attributes spread onto the tooltip div
Keyboard Interactions
- Escape: The consumer should hide the tooltip when Escape is pressed (not built into the component; must be handled by the consumer)
- The tooltip itself does not receive focus; it is a supplementary description for another element
ARIA
role="tooltip" -- identifies the element as a tooltip, a popup that displays a description for an element
id={id} -- used with aria-describedby on the trigger element to create an accessible association between the trigger and the tooltip
When to Use
- Use Tooltip to provide brief, supplementary descriptions for UI elements on hover or focus, such as explaining an icon button's purpose.
- Use to clarify abbreviations, technical terms, or truncated text.
- Use when the information is helpful but not essential for completing a task.
- Use for labelling icon-only buttons where a visible label would not fit.
- Use for showing full text when content is truncated with ellipsis.
When Not to Use
- Do not use for critical information that users must see -- use inline text or Alert instead.
- Do not use for interactive content such as links, buttons, or forms -- use Popover instead.
- Do not use for long text -- keep tooltip content to one short sentence.
- Do not use for rich content previews -- use HoverCard instead.
Headless
This headless component provides a <div> with role="tooltip" and conditional rendering (fully removed from DOM when hidden). The consumer manages visibility toggling (hover, focus events), positioning, and all visual styling including background, border, and arrow indicators.
Styles
The consumer provides all CSS styling. The component renders with a .tooltip class for targeting. No default styles are included — this is a fully headless component.
Testing
- Verify the component renders a
<div> element with class tooltip
- Verify role="tooltip"` -- identifies the element as a tooltip, a popup that displays a description for an element
- Verify keyboard interactions work correctly
- Verify pass-through attributes are applied
Advice
- Designers: Keep tooltip text concise (one line if possible). Position tooltips so they do not obscure the trigger element or important content.
- Developers: Link the tooltip to its trigger using
id and aria-describedby. Handle Escape key to dismiss the tooltip and ensure it works on both hover and focus for keyboard accessibility.
Implementation Notes
- Renders a
<div> with role="tooltip" when visible, removed from the DOM when hidden
- Uses conditional rendering, so the tooltip is fully removed from the DOM when not shown
- Supports two-way binding on the
visible prop
- The consumer is responsible for managing visibility (e.g., on hover/focus of a trigger element)
- The
id prop enables linking the tooltip to its trigger element via aria-describedby
- Spreads
restProps onto the div element for consumer extensibility
Related components
hover-card — a card that appears on hover over a trigger element
popover — a floating content box anchored to a trigger element
contextual-help — a help button that opens a popover with explanatory content
References
- WAI-ARIA Tooltip Pattern: https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/
- MDN aria-describedby: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-describedby
Canonical contract
Generated from this component's canonical metadata — the machine-checked source the implementations are held to.
Metadata
- Component: tooltip
- PascalCase: Tooltip
- Description: a small popup showing descriptive text on hover or focus
- Status: stable — exercised in composed page flows under e2e and axe, beyond the per-component checks
- HTML tag: <div>
- CSS class: .tooltip
- Interactive: yes
ARIA
role="tooltip" -- identifies the element as a tooltip, a popup that displays a description for an element id={id} -- used with aria-describedby on the trigger element to create an accessible association between the trigger and the tooltip
Keyboard
- Escape: The consumer should hide the tooltip when Escape is pressed (not built into the component; must be handled by the consumer)
- The tooltip itself does not receive focus; it is a supplementary description for another element
Props
label: string (required) -- the tooltip text content visible: boolean (default: false) -- bindable boolean controlling whether the tooltip is shown id: string (default: undefined) -- optional id for linking to a trigger element via aria-describedby ...restProps: unknown -- additional attributes spread onto the tooltip div