Skip to content

Tooltip

WxTooltip says what a control is. That is all it does.

A row of icon buttons, each with a name
The first tip waits; the ones after it come at once, because by then you have said what you are doing.
Sides
More than a word

Usage

vue
<template>
  <wx-tooltip content="Delete">
    <wx-action type="remove" @click="remove" />
  </wx-tooltip>
</template>

The slot takes exactly one element, and the tip attaches to it directly — no wrapper goes into the layout, and the tip belongs to the thing that is actually focused.

A tip, not a panel

It cannot be clicked into, it never holds a button, and it is gone the moment the pointer leaves. Anything a reader has to reach for is a Popover; anything they have to answer is a Popconfirm.

Which also means: never put anything in a tooltip that is only in a tooltip. A touch screen has no hover, and a keyboard reaches it only by focusing the control. If it matters, it belongs on the page.

What it is good for

Icon-only buttons, mainly. A row of glyphs at the end of a table row is unreadable without them — and a title attribute is not a substitute: it appears after a second of stillness, in the browser's own styling, and never at all on a touch screen.

On a touch screen it never opens

That is deliberate, not a gap. A tooltip answers hovering, and a finger does not hover: the only gesture it has is the tap, which already belongs to the control the tip is attached to. Opening one on tap would mean every icon button did nothing the first time it was pressed.

So a phone gets no tips at all, which is why nothing may live only in one. What replaces it depends on what the tip was doing:

The tip saidOn a phone
What an icon-only button isShow the label. There is room in a sheet or a menu row
Something worth readingA Popover, which a tap opens and closes
Something the control must sayaria-label, which is what a screen reader was reading anyway

Delays, and the group

The first tip in a group waits 150 ms before appearing; the ones after it come at once. By the time a reader has hovered one icon and moved to the next, they have said what they are doing, and making them wait again for each one is how a toolbar comes to feel slow.

The grouping is per component, which is the right scope: a toolbar's tips are a group, a page's tips are not.

Props

PropTypeDefaultDescription
contentstringThe text
side'top' | 'right' | 'bottom' | 'left''top'Preferred side; it flips when there is no room
align'start' | 'center' | 'end''center'How it lines up along that side
offsetnumber6Distance from the trigger
delaynumber150How long the pointer rests before it opens
arrowbooleantrueThe little pointer
maxWidthnumber | string260Before it wraps
disabledbooleanfalseNothing opens
teleportbooleantrueEscapes overflow: hidden

Models: v-model:open — for showing one from elsewhere, such as a hint after a failed save.

Slots: default — the control, exactly one element; content — the tip.

On a touch screen

Nothing opens. A phone has no hover, so the tap that would open a tip is the tap that was meant for the button under it: the reader gets a black label over what they were aiming at while the button does its job underneath. The question is asked once for the whole application — matchMedia('(hover: hover)'), through useHoverPointer() — and a tablet that gains a mouse changes the answer without a reload.

A tip opened from code with v-model:open is left alone: that one is deliberate rather than a side effect of pointing. And because this only takes away what a touch device never had, what a control means still has to be written somewhere a screen reader can reach — WxAction puts it in aria-label.

Accessibility

The tip is bound to its trigger, so it is announced when the control is focused as well as hovered, and Escape closes it. It takes no pointer events of its own: the tip belongs to whatever is under the pointer, never to the pointer.

Released under the MIT License.