Tooltip

A short label beside a control on hover and keyboard focus.

StableSince 1.0.0
On this page

Import

import { Tooltip } from '@envsemble/envui';

Usage

Tooltip wraps the one control it describes, its children, such as an IconButton, which takes the trigger's props and ref; content is its text.

  • While it is open, a control with a name of its own is described by it, through aria-describedby, so name an icon-only control with aria-label too.
  • The pointer rests on the control for delay, 400 ms by default, before it opens, and keyboard focus opens it at once; defaultOpen starts it open, and open with onOpenChange, which receives why, lets the application open it, such as for a step of a tour.
IconActions.tsx
import { IconButton, Tooltip, Row } from '@envsemble/envui';
import { IconDownload } from '@envsemble/envui/icons/Download';
import { IconRefresh } from '@envsemble/envui/icons/Refresh';
import { IconShare } from '@envsemble/envui/icons/Share';

const actions = [
  { label: 'Refresh members', icon: <IconRefresh /> },
  { label: 'Download as CSV', icon: <IconDownload /> },
  { label: 'Share list', icon: <IconShare /> },
];

export default function IconActions() {
  return (
    <Row wrap align="center" gap={4}>
      {actions.map(({ label, icon }, index) => (
        // The tooltip shows the name the button already has. The first is shown open in the
        // docs; without defaultOpen, each opens on hover and focus.
        <Tooltip key={label} content={label} defaultOpen={index === 0}>
          <IconButton icon={icon} aria-label={label} />
        </Tooltip>
      ))}
    </Row>
  );
}

Side

side is top, the default, bottom, left, right, or inline-start and inline-end, which follow the text direction. Where the window has no room, it flips to the other side. align lines it up with the control along that side: start, center, the default, or end.

<Tooltip content="Show files" side="inline-end">
  <IconButton icon={<IconFolder />} aria-label="Show files" variant="ghost" />
</Tooltip>

A Tooltip can be the trigger of a Menu.Root, Popover, Dialog, Sheet or ConfirmDialog: its native props and ref reach the control, and it stays closed while their popup is open and as focus returns to the control. Around a HoverCard it shows nothing.

<Menu.Root
  aria-label="Project actions"
  trigger={
    <Tooltip content="More actions">
      <IconButton icon={<IconMoreVert />} aria-label="More actions" />
    </Tooltip>
  }
>
  <Menu.Item icon={<IconArchive />}>Archive</Menu.Item>
</Menu.Root>

Keyboard shortcuts

Write the shortcut after the name in content, and give the control aria-keyshortcuts in ARIA's key names, such as Control+B.

<Tooltip content="Bold (Ctrl+B)" side="bottom">
  <IconButton icon={<IconFormatBold />} aria-label="Bold" aria-keyshortcuts="Control+B" />
</Tooltip>

Text and disabled controls

Text that isn't a control takes the dotted underline, env-hover-detail, with the arrow pointer rather than the text cursor; hover cards and relative times on text take the same underline, and buttons, icon buttons and links keep their own look. Give it tabIndex={0}, so keyboard focus opens the tooltip too. A disabled control sits in a wrapper, env-tooltip-disabled-target, that takes the pointer and focus for it, and carries its role, name, state and aria-disabled.

<Tooltip content="Central European Time">
  <abbr tabIndex={0}>CET</abbr>
</Tooltip>

Customize

popupClassName adds a class to the popup, env-tooltip, beside its own; its positioner is env-tooltip-positioner.

A tooltip is frosted, as every popup is: --env-color-bg-neutral-strong at --env-tooltip-opacity, 82 %, over --env-popup-blur, with a smaller shadow of its own, --env-tooltip-shadow, and no edge. Set them on a .env-theme boundary, as Popover describes the popups' own. At high contrast, with reduced transparency and under forced colors it is solid, with its edge and no shadow. A Kbd in it is a flat chip of its text color, with the keys of a combination side by side.

Accessibility

You provide

  • An accessible name on the control, such as aria-label on an icon-only button.
  • The reason a control is disabled in the page too.
  • A child that takes the trigger's props and ref, such as a Button or an IconButton.

envUI provides

  • role="tooltip", describing a named control while it is open.
  • A focusable wrapper around a disabled control, named as the control and reported disabled.
  • A tooltip that stays open while the pointer moves onto it.

Props

Tooltip

A short label beside a control, shown while the pointer rests on it or it has keyboard focus, such as an icon-only button's name or why a control is disabled. It closes on Esc and when the control is pressed, and stays closed while the control's own popup, such as a menu, is open. Native props and ref go to the control, so a Tooltip can be the trigger of a Menu.Root or Popover; popupClassName styles the tooltip's popup.

PropTypeDescription
contentrequired
ReactNode
What the tooltip shows: a short, supplementary text, such as an icon-only control's name or why a control is disabled. While it is open, a control with a name of its own is described by it (aria-describedby); never the only place essential information appears.
childrenrequired
ReactElement<TriggerProps>
The one control it describes, such as an IconButton, which takes the trigger's props and ref, and the Tooltip's own native props and ref. Around a Menu.Root, Popover, Dialog, Sheet or ConfirmDialog, the tooltip describes their `trigger`; around a HoverCard, it shows nothing. A disabled control is wrapped in an element that hovering opens the tooltip on. Around a button, link, tab or menu item, it is focusable and carries the control's name, role and state, reported disabled, so keyboard focus opens it too. One element: text, a Fragment or a component that doesn't pass the ref on to its element gets no tooltip, and says so while developing. Text, such as a focusable span or Text that holds text, takes a quiet dotted underline, env-hover-detail.
ref
Ref<HTMLElement>
The control's ref, as the Tooltip passes its props on to the control, such as when the Tooltip is the `trigger` of a Menu.Root or Popover, which give their trigger a ref.
popupClassName
string
Class of the tooltip's popup, beside env-tooltip.
sideDefault 'top'
'top''bottom''left''right''inline-start''inline-end'
The side of the control it opens on: top, bottom, left, right, or inline-start and inline-end, which follow the text direction. Where the window has no room, it flips to the other side.
alignDefault 'center'
'start''center''end'
How the tooltip lines up with the control along that side: its start, center or end.
delayDefault 400
number
Milliseconds the pointer rests on the control before the tooltip opens; keyboard focus opens it at once.
defaultOpenDefault false
boolean
Whether the tooltip starts open, such as in a picture of the interface; it then closes as an opened one does.
open
boolean
Whether the tooltip shows, for a tooltip the application controls with onOpenChange, such as one a step of a tour opens.
onOpenChange
(open: boolean, details: TooltipOpenChangeDetails) => void
Receives the requested state, and why, as the pointer rests on the control or leaves it, focus reaches or leaves it, it is pressed or Esc closes the tooltip.

Also accepts the native props of <button>, such as ref, className and aria-* attributes.

Part names

Each part's class and state attributes are public and versioned, for an application's CSS to style.

env-tooltip
The tooltip.
env-tooltip-disabled-target
The wrapper that lets a disabled control show a tooltip.
env-tooltip-positioner
The tooltip's positioner.
data-ending-style
Any value, or present
data-starting-style
Any value, or present

Color properties

Each sets a color of one instance, through style or CSS; its hover, focus and press follow it. They are public and versioned.

--env-tooltip-container
The fill.
--env-tooltip-content
The text and the keys of a shortcut.
--env-tooltip-outline
The edge.

Changelog

1.0.0

A text trigger, such as a focusable span or Text that holds text, takes a quiet dotted underline, env-hover-detail. The tooltip describes a named control (aria-describedby) while it is open; a disabled button's, link's, tab's or menu item's wrapper carries its role, name, state and aria-disabled; a Kbd inside takes light key caps; native props and ref reach the control, so a Tooltip can be the trigger of a Menu.Root, Popover, Dialog, Sheet or ConfirmDialog, and goes to their trigger around one; it stays closed while the control's menu or popover is open, and when focus returns to the control as it closes; around a HoverCard it shows nothing; popupClassName styles the popup; it renders on PopupSurface, in the control's text direction.

1.0.0-prerelease.6

A tooltip only fades, in --env-motion-duration-fast with --env-motion-ease-enter, rather than growing in as the larger popups do, so it shows from its first frames.

1.0.0-prerelease.5

open and onOpenChange, and align, as on Popover.

Tooltips are frosted: the strong fill at 82 % over a blur, with 0.75 rem corners, a small soft shadow and no edge, and solid with their edge at high contrast, with reduced transparency and under forced colors. A Kbd inside is a flat chip with no edge, its keys side by side, and the tooltip opens 8 px from its control, as every popup does.