Pro--% off in--d : --h : --m : --s
HeroUI

Tooltip

Migration guide for Tooltip from HeroUI v2 to v3

Refer to the v3 Tooltip documentation for complete API reference, styling guide, and advanced examples. This guide only focuses on migrating from HeroUI v2.

Structure Changes

In v2, Tooltip used a content prop:

import { Tooltip, Button } from "@heroui/react";

export default function App() {
  return (
    <Tooltip content="I am a tooltip">
      <Button>Hover me</Button>
    </Tooltip>
  );
}

In v3, Tooltip requires compound components:

import { Tooltip, Button } from "@heroui/react";

export default function App() {
  return (
    <Tooltip>
      <Tooltip.Trigger>
        <Button>Hover me</Button>
      </Tooltip.Trigger>
      <Tooltip.Content>
        I am a tooltip
      </Tooltip.Content>
    </Tooltip>
  );
}

Key Changes

1. Component Structure

v2: Simple Tooltip with content prop and children as trigger
v3: Compound components (Tooltip.Trigger, Tooltip.Content, Tooltip.Arrow)

2. Prop Changes

v2 Propv3 LocationNotes
contentUse Tooltip.Content children
showArrowshowArrow (on Content)Moved to Tooltip.Content
placementplacement (on Content)Moved to Tooltip.Content
offsetoffset (on Content)Moved to Tooltip.Content
colorRemoved (use Tailwind CSS)
sizeRemoved (use Tailwind CSS)
radiusRemoved (use Tailwind CSS)
shadowRemoved (use Tailwind CSS)
classNamesUse className props on individual components
motionPropsRemoved (animations handled differently)
triggertrigger (on root)Still exists: "hover" | "focus" (default "hover")
isDisabledisDisabled (on root)New in v3: disables the tooltip entirely
delaydelay (on root)Still exists (default changed from 0 to 700)
closeDelaycloseDelay (on root)Still exists (default 0)
portalContainerNot exposed
updatePositionDepsNot exposed
containerPadding, crossOffsetNot exposed
shouldFlipHandled automatically
triggerScaleOnOpenNot available
isKeyboardDismissDisabledNot available
isDismissableNot available
shouldCloseOnBlurNot available
shouldCloseOnInteractOutsideNot available
onCloseUse onOpenChange instead

3. Props Moved to Tooltip.Content

  • showArrow - Now on Tooltip.Content
  • placement - Now on Tooltip.Content
  • offset - Now on Tooltip.Content

Migration Examples

Content Configuration

{/* With arrow */}
<Tooltip content="I am a tooltip" showArrow>
  <Button>Hover me</Button>
</Tooltip>

{/* With placement */}
<Tooltip content="Tooltip" placement="bottom">
  <Button>Hover me</Button>
</Tooltip>

{/* With offset */}
<Tooltip content="Tooltip" offset={12}>
  <Button>Hover me</Button>
</Tooltip>
{/* With arrow */}
<Tooltip delay={0}>
  <Tooltip.Trigger>
    <Button>Hover me</Button>
  </Tooltip.Trigger>
  <Tooltip.Content showArrow>
    <Tooltip.Arrow />
    <p>I am a tooltip</p>
  </Tooltip.Content>
</Tooltip>

{/* With placement */}
<Tooltip delay={0}>
  <Tooltip.Trigger>
    <Button>Hover me</Button>
  </Tooltip.Trigger>
  <Tooltip.Content placement="bottom">
    <p>Tooltip</p>
  </Tooltip.Content>
</Tooltip>

{/* With offset */}
<Tooltip delay={0}>
  <Tooltip.Trigger>
    <Button>Hover me</Button>
  </Tooltip.Trigger>
  <Tooltip.Content offset={12}>
    <p>Tooltip</p>
  </Tooltip.Content>
</Tooltip>

Controlled Tooltip

import { useState } from "react";

const [isOpen, setIsOpen] = useState(false);

<Tooltip
  content="I am a tooltip"
  isOpen={isOpen}
  onOpenChange={setIsOpen}
>
  <Button>Hover me</Button>
</Tooltip>
import { useState } from "react";

const [isOpen, setIsOpen] = useState(false);

<Tooltip isOpen={isOpen} onOpenChange={setIsOpen} delay={0}>
  <Tooltip.Trigger>
    <Button>Hover me</Button>
  </Tooltip.Trigger>
  <Tooltip.Content>
    <p>I am a tooltip</p>
  </Tooltip.Content>
</Tooltip>

With Delay

<Tooltip content="Tooltip" delay={500} closeDelay={200}>
  <Button>Hover me</Button>
</Tooltip>
<Tooltip delay={500} closeDelay={200}>
  <Tooltip.Trigger>
    <Button>Hover me</Button>
  </Tooltip.Trigger>
  <Tooltip.Content>
    <p>Tooltip</p>
  </Tooltip.Content>
</Tooltip>

Custom Content

<Tooltip
  content={
    <div>
      <strong>Title</strong>
      <p>Description</p>
    </div>
  }
>
  <Button>Hover me</Button>
</Tooltip>
<Tooltip delay={0}>
  <Tooltip.Trigger>
    <Button>Hover me</Button>
  </Tooltip.Trigger>
  <Tooltip.Content>
    <div>
      <strong>Title</strong>
      <p>Description</p>
    </div>
  </Tooltip.Content>
</Tooltip>

With Custom Trigger

<Tooltip content="Tooltip">
  <div className="custom-trigger">Custom trigger</div>
</Tooltip>
<Tooltip delay={0}>
  <Tooltip.Trigger className="custom-trigger">
    <div>Custom trigger</div>
  </Tooltip.Trigger>
  <Tooltip.Content>
    <p>Tooltip</p>
  </Tooltip.Content>
</Tooltip>

Component Anatomy

The v3 Tooltip follows this structure:

Tooltip (Root)
  ├── Tooltip.Trigger
  │   └── [Trigger element]
  └── Tooltip.Content
      ├── Tooltip.Arrow (optional)
      └── [Tooltip content]

New Props in v3

isDisabled

The isDisabled prop allows you to completely disable the tooltip. When disabled, the tooltip will not appear on hover or focus:

<Tooltip isDisabled>
  <Tooltip.Trigger>
    <Button>No tooltip</Button>
  </Tooltip.Trigger>
  <Tooltip.Content>
    <p>This will not show</p>
  </Tooltip.Content>
</Tooltip>

trigger

The trigger prop controls how the tooltip is activated. It accepts "hover" (default) or "focus":

{/* Show tooltip only on focus */}
<Tooltip trigger="focus">
  <Tooltip.Trigger>
    <Button>Focus me</Button>
  </Tooltip.Trigger>
  <Tooltip.Content>
    <p>Shown on focus only</p>
  </Tooltip.Content>
</Tooltip>

Custom Render Function

Tooltip.Content and Tooltip.Arrow both support a render prop that allows you to override the default DOM element with a custom render function for advanced use cases.

Important Notes

Content Prop

  • v2: Used content prop for tooltip text/content
  • v3: Content goes as children of Tooltip.Content component

Arrow

  • v2: Controlled by showArrow prop on root
  • v3: Use showArrow prop on Tooltip.Content and include Tooltip.Arrow component

Placement and Offset

  • v2: placement and offset props on root
  • v3: placement and offset props moved to Tooltip.Content

Trigger Element

  • v2: Children were automatically used as trigger
  • v3: Must wrap trigger element in Tooltip.Trigger component

Default Delay

  • v2: delay default was 0
  • v3: delay default is 700 (note: examples use delay={0} to match v2 behavior)

Summary

  1. Component Structure: Must use compound components (Tooltip.Trigger, Tooltip.Content, Tooltip.Arrow)
  2. Content Prop Removed: content prop removed - use Tooltip.Content children
  3. Props Moved: showArrow, placement, offset moved to Tooltip.Content
  4. Styling Props Removed: color, size, radius, shadow - use Tailwind CSS
  5. ClassNames Removed: Use className props on individual components
  6. Motion Props Removed: motionProps removed - animations handled differently
  7. Advanced Props Removed: Many positioning and behavior props removed
  8. Default Delay Changed: Default delay changed from 0 to 700
  9. isDisabled Prop: New isDisabled prop to completely disable the tooltip
  10. trigger Prop: Accepts "hover" (default) or "focus" to control activation method
  11. Render Props: Tooltip.Content and Tooltip.Arrow support a render prop for custom DOM rendering

On this page