27.5k

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.

Overview

The Tooltip component in HeroUI v3 has been redesigned with a compound component pattern, requiring explicit structure with Tooltip.Trigger, Tooltip.Content, and Tooltip.Arrow components. The content prop has been removed.

Structure Changes

v2: Content Prop

In v2, Tooltip used a content prop:

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

<Tooltip content="I am a tooltip">
  <Button>Hover me</Button>
</Tooltip>

v3: Compound Components

In v3, Tooltip requires compound components:

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

<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 PropNotes
content-Removed (use Tooltip.Content children)
showArrowshowArrow (on Tooltip.Content)Moved to Tooltip.Content
placementplacement (on Tooltip.Content)Moved to Tooltip.Content
offsetoffset (on Tooltip.Content)Moved to Tooltip.Content
color-Removed (use Tailwind CSS)
size-Removed (use Tailwind CSS)
radius-Removed (use Tailwind CSS)
shadow-Removed (use Tailwind CSS)
classNames-Use className props
motionProps-Removed (animations handled differently)
triggertrigger (on root)Still exists, but simplified
delaydelay (on root)Still exists
closeDelaycloseDelay (on root)Still exists

3. Removed Props

The following props are no longer available in v3:

  • content - Use Tooltip.Content children instead
  • color, size, radius, shadow - Use Tailwind CSS classes
  • classNames - Use className props on individual components
  • motionProps - Animations handled differently
  • portalContainer - Not exposed
  • updatePositionDeps - Not exposed
  • containerPadding, crossOffset - Not exposed
  • shouldFlip - Handled automatically
  • triggerScaleOnOpen - Not available
  • isKeyboardDismissDisabled - Not available
  • isDismissable - Not available
  • shouldCloseOnBlur - Not available
  • shouldCloseOnInteractOutside - Not available
  • onClose - Use onOpenChange instead

4. Props Moved to Tooltip.Content

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

Migration Examples

Basic Usage

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

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

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

With Arrow

<Tooltip content="I am a tooltip" showArrow>
  <Button>Hover me</Button>
</Tooltip>
<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 content="Tooltip" placement="bottom">
  <Button>Hover me</Button>
</Tooltip>
<Tooltip delay={0}>
  <Tooltip.Trigger>
    <Button>Hover me</Button>
  </Tooltip.Trigger>
  <Tooltip.Content placement="bottom">
    <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>

Custom Styling

<Tooltip
  content="Tooltip"
  color="primary"
  size="lg"
  classNames={{
    base: "custom-base",
    content: "custom-content"
  }}
>
  <Button>Hover me</Button>
</Tooltip>
<Tooltip delay={0}>
  <Tooltip.Trigger>
    <Button>Hover me</Button>
  </Tooltip.Trigger>
  <Tooltip.Content className="custom-content bg-accent text-accent-foreground">
    <p>Tooltip</p>
  </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>

With Offset

<Tooltip content="Tooltip" offset={12}>
  <Button>Hover me</Button>
</Tooltip>
<Tooltip delay={0}>
  <Tooltip.Trigger>
    <Button>Hover me</Button>
  </Tooltip.Trigger>
  <Tooltip.Content offset={12}>
    <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]

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)

Breaking Changes 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

Tips for Migration

  1. Update structure: Wrap trigger in Tooltip.Trigger and content in Tooltip.Content
  2. Remove content prop: Move content to Tooltip.Content children
  3. Add arrow: Use showArrow on Tooltip.Content and include Tooltip.Arrow component
  4. Move placement: Move placement prop to Tooltip.Content
  5. Move offset: Move offset prop to Tooltip.Content
  6. Update styling: Replace styling props with Tailwind CSS classes
  7. Update classNames: Replace classNames prop with className props on individual components
  8. Set delay: If you need immediate tooltip (like v2 default), set delay={0}

Need Help?

For v3 Tooltip features and API:

For community support: