Tooltip

A tooltip shows a short label for a control when people hover over it or focus it, such as the name of an icon button.

A tooltip shows a few words next to a control while the pointer rests on it or keyboard focus is on it. Use it to name an icon-only button or to show a keyboard shortcut. Content people need to read or act on belongs on the page, or in a Popover that opens on a press.

Playground

Usage

import { Button, Flex, Tooltip } from '@kushagradhawan/kookie-ui';
import { HugeiconsIcon } from '@hugeicons/react';
import { Delete02Icon, Settings02Icon } from '@hugeicons/core-free-icons';
 
export function RowActions() {
  return (
    <Flex gap="1">
      <Tooltip content="Settings">
        <Button iconOnly emphasis="quiet" aria-label="Settings">
          <HugeiconsIcon icon={Settings02Icon} strokeWidth={1.75} />
        </Button>
      </Tooltip>
      <Tooltip content="Delete">
        <Button iconOnly emphasis="quiet" color="red" aria-label="Delete">
          <HugeiconsIcon icon={Delete02Icon} strokeWidth={1.75} />
        </Button>
      </Tooltip>
    </Flex>
  );
}

Button also takes a tooltip prop that does the same in one line: <Button iconOnly tooltip="Settings" aria-label="Settings">.

Best practices

Keep it to a few words. A tooltip names or adds one detail, such as "Copy link" or "Bold ⌘B". Anything longer belongs in the interface, where people can read it at their own pace.

Don't put the only copy of important information in it. Touch screens can't hover, and people who never move the pointer over the control never see it. A tooltip repeats or adds to what's visible. It never replaces it.

Don't put controls in it. The tooltip closes when the pointer leaves, and it can't take focus. Use a Popover for buttons and links.

Still label the control. An icon-only button needs its own aria-label. The tooltip describes the control, but it doesn't give it a name.

Don't add one to a control that already has a visible label. "Save" with a tooltip that says "Save" adds a delay and no meaning.

Placement

side sets where the tooltip opens: 'top' by default, or 'right', 'bottom' or 'left'. align lines it up with the control's 'start', 'center' or 'end'. The tooltip sits 4px from the control, flips to the opposite side when there is no room, and stays at least 10px inside the window. Its width stops at 360px and longer text wraps.

Delay

A tooltip opens after the pointer rests for 200ms. Set delayDuration on one tooltip to change it.

Wrap the app in TooltipProvider once, inside Theme. Then, once one tooltip is open, moving to the next control shows its tooltip at once, so people can scan a toolbar. Without it, each tooltip waits on its own.

import { Theme, TooltipProvider } from '@kushagradhawan/kookie-ui';
 
<Theme>
  <TooltipProvider>{children}</TooltipProvider>
</Theme>

Examples

Keyboard shortcut

Pair the action's name with its shortcut, so people learn it while they use the pointer.

<Tooltip content="Bold ⌘B">
  <Button iconOnly emphasis="quiet" aria-label="Bold">
    <HugeiconsIcon icon={TextBoldIcon} strokeWidth={1.75} />
  </Button>
</Tooltip>

Truncated text

When a label is cut short with an ellipsis, a tooltip can show the full text. The trigger must be able to take focus, such as a link or a button, so keyboard users can reach it too.

Side placement in a sidebar

In a narrow sidebar of icon buttons, set side="right" so the tooltip opens into the page instead of over the next button.

<Tooltip content="Projects" side="right">
  <Button iconOnly emphasis="quiet" aria-label="Projects">
    <HugeiconsIcon icon={Folder01Icon} strokeWidth={1.75} />
  </Button>
</Tooltip>

Props

Tooltip

PropTypeDefaultDescription
contentReactNodeRequired. The text shown in the tooltip
childrenReactElementRequired. One element that triggers the tooltip
side'top' | 'right' | 'bottom' | 'left''top'Which side of the control it opens on
align'start' | 'center' | 'end''center'How it lines up with the control
sideOffsetnumber4The gap to the control, in pixels
collisionPaddingnumber10The space kept from the window's edges
delayDurationnumber200Milliseconds before it opens
disableHoverableContentbooleanfalseCloses the tooltip when the pointer moves onto it
openbooleanThe open state. Controlled
defaultOpenbooleanfalseThe open state on first render
onOpenChange(open: boolean) => voidCalled when the tooltip opens or closes
widthstring, responsiveA fixed width
minWidthstring, responsiveThe narrowest width
maxWidthstring, responsive'360px'The widest width
containerHTMLElementdocument.bodyWhere the portal renders
forceMountbooleanKeeps the tooltip in the DOM while closed

Tooltip also accepts the attributes of the HTML div element that holds the text, and its ref points to that element.

TooltipProvider

PropTypeDefaultDescription
delayDurationnumber200Milliseconds before the first tooltip opens
skipDelayDurationnumber300How long after one closes the next still opens at once
disableHoverableContentbooleanfalseCloses tooltips when the pointer moves onto them

Accessibility

KeyAction
TabMoving focus to the control opens its tooltip
EscapeCloses the tooltip
  • Name: The control keeps its own name. A screen reader announces the tooltip text as the control's description, after its name.
  • Role: The text has role="tooltip" and the control points to it with aria-describedby while it is open.
  • Focus: The tooltip never takes focus. It opens on keyboard focus and closes when focus leaves.
  • Trigger: The child must be an element that can take focus, such as a Button. A tooltip on plain text or a disabled button can't be reached with the keyboard.
  • Touch: Touch screens don't show tooltips on hover. Make sure the control is clear without one.