Skip to content
Components, switch product

Tooltip

<gui-tooltip> describes another element in a few words. It shows next to the element while the pointer rests on it or while it has keyboard focus, and screen readers read its text as the element’s description. Its children are the text.

Saves your changes without publishing them.
Code of the example above
TooltipBasic.tsx
import { GuiTooltip } from '@golemui/gui-components/react';
import '@golemui/gui-components/index.css';
export function TooltipBasic() {
return (
<>
<button
type="button"
id="save-draft"
className="gui-button gui-button--outlined"
>
Save draft
</button>
<GuiTooltip htmlFor="save-draft">
Saves your changes without publishing them.
</GuiTooltip>
</>
);
}

The element’s entry point is @golemui/gui-components/tooltip, which registers <gui-tooltip> and nothing else. To install the package and load the stylesheet, see Installation.

The @golemui/gui-components/react components have typed props and an on* prop for each event. React 18 or later.

TooltipExample.tsx
import { GuiTooltip } from '@golemui/gui-components/react';
import '@golemui/gui-components/index.css';
export function TooltipExample() {
return (
<GuiTooltip
htmlFor="save-draft"
>
Saves your changes without publishing them.
</GuiTooltip>
);
}

for takes the id of the element the tooltip describes, its target, as on a <label>. In React, it is the htmlFor prop. Put the tooltip anywhere: it shows next to its target, above the rest of the page.

The target is the element that takes the pointer and the focus, such as a native button, link or input. On a gui-* element, the focus goes to the control inside it, and keyboard focus doesn’t show the tooltip. To give a native button the look of a gui-button, add the gui-button class, and gui-button--outlined for the outlined style, as these examples do. For a field, use its hint, which is always visible.

Properties

Property Type Default Description
htmlFor attribute for string – The id of the element the tooltip describes.
placement GuiPlacement 'top' Where the tooltip sits next to its target. Start and end follow the reading direction.
openDelay attribute open-delay number 500 How long the pointer or focus rests on the target before the tooltip opens, in ms.
closeDelay attribute close-delay number 150 How long it stays after the pointer leaves, in ms: time to move the pointer onto it.
open boolean – Whether the tooltip is open. Setting it opens or closes it and fires no gui-toggle.

Events

Every event bubbles and is composed, so you can listen on any ancestor.

Event Description
gui-toggle The tooltip opened or closed, from the pointer, focus or Escape. detail.open is the new state.

placement sets the side of the target the tooltip shows on: top, the default, or any of the values of the popover. When it doesn’t fit, it moves to the other side. An arrow points at the target, wherever the tooltip ends up.

open-delay is how long the pointer or the focus rests on the target before the tooltip shows, 500ms by default, so it doesn’t flash while the pointer crosses the page. close-delay is how long it stays after the pointer leaves, 150ms by default: time to move the pointer onto it.

Anyone with the link can view the board.
Code of the example above
TooltipPlacement.tsx
import { GuiTooltip } from '@golemui/gui-components/react';
import '@golemui/gui-components/index.css';
export function TooltipPlacement() {
return (
<>
<button
type="button"
id="copy-link"
className="gui-button gui-button--outlined"
>
Copy link
</button>
<GuiTooltip htmlFor="copy-link" placement="bottom" openDelay={200}>
Anyone with the link can view the board.
</GuiTooltip>
</>
);
}

A disabled control gets no pointer or focus events, so its tooltip never shows: yet that is where a tooltip that explains why helps most. Mark the button aria-disabled="true" instead of disabled: it stays in the tab order and shows its tooltip, and your click handler does nothing while it is set. Or put the tooltip on an element around the disabled control.

Add a title before you publish.
Code of the example above
TooltipDisabled.tsx
import { GuiTooltip } from '@golemui/gui-components/react';
import '@golemui/gui-components/index.css';
export function TooltipDisabled() {
return (
<>
<button
type="button"
id="publish-post"
className="gui-button"
aria-disabled="true"
>
Publish
</button>
<GuiTooltip htmlFor="publish-post">
Add a title before you publish.
</GuiTooltip>
</>
);
}

Set open to show or hide the tooltip yourself. Setting it fires no gui-toggle. When the pointer, the focus or Escape shows or hides it, the element fires gui-toggle with the new state in event.detail.open, and open follows.

The element is the tooltip’s box. When it connects, it gives itself the tooltip role, popover="manual" and an id, unless you set them, and adds that id to its target’s aria-describedby. While it is open, the stylesheet points an arrow at the target:

gui-tooltip
<button type="button" id="save-draft" aria-describedby="gui-tooltip-1">
Save draft
</button>
<gui-tooltip
for="save-draft"
popover="manual"
role="tooltip"
id="gui-tooltip-1"
open
data-gui-arrow="bottom"
>
Saves your changes without publishing them.
</gui-tooltip>

Until it opens, and before the element upgrades, the tooltip is hidden, so its text never shows in the flow of a server-rendered page. While it is open, the element places it with inline styles and gives the arrow its edge in data-gui-arrow and its offset along that edge in --gui-arrow-offset. Leave those alone. See Floating panels.

The tooltip reads these design tokens. Set them on :root to change every tooltip, or on any element to change the tooltips inside it:

TokenWhat it styles
--gui-tooltip-bgThe background and the arrow. Defaults to --gui-bg-inverse.
--gui-tooltip-textThe text. Defaults to --gui-text-inverse.
--gui-tooltip-max-widthThe widest the tooltip gets, 20rem by default. Longer text wraps.
--gui-radius-smThe corner radius.
--gui-space-1The padding above and below the text.
--gui-space-2The padding before and after the text.
--gui-font-xsThe text size.
--gui-overlay-durationHow long the tooltip takes to fade in and out. Reduced motion skips it.

--gui-tooltip-bg and --gui-tooltip-text also color the value bubbles of the slider.

styles.css
/* Tooltips in the brand color. */
:root {
--gui-tooltip-bg: #2f3a8f;
--gui-tooltip-text: #ffffff;
}

To restyle beyond the tokens, see Overriding styles; for dark mode and the Clay theme, see Themes and dark mode.

The tooltip meets WCAG 1.4.13, Content on Hover or Focus:

  • Dismissible. Escape hides it without moving the pointer or the focus, and does nothing else: it doesn’t close the dialog the target is in.
  • Hoverable. The pointer can move from the target onto the tooltip without it closing.
  • Persistent. It stays until the pointer leaves the target and the tooltip, the focus leaves the target, or the user presses Escape or the target.

And:

  • Description. The tooltip’s text is the target’s description, through aria-describedby. It is not its name: the target needs a name of its own, such as its text or an aria-label.
  • Keyboard focus only. Focus from the keyboard shows the tooltip. Focus from a click doesn’t: pressing the target hides it, since the user acted on what it described.
  • Touch. A tap never shows the tooltip: it activates the target. Don’t put anything in a tooltip that touch users need and can’t find elsewhere.
  • Text only. The tooltip isn’t focusable, so links and buttons in it can’t be reached. For content the user interacts with, use a popover.
KeyAction
TabTo the target: shows the tooltip after open-delay.
EscapeHides the tooltip. The focus stays on the target.

What every element shares is in Accessibility.