Back to Prisma

Tooltip

apps/eclipse/content/design-system/components/tooltip.mdx

latest15.4 KB
Original Source

import { Tooltip, TooltipContent, TooltipTrigger, TooltipExample, Button } from "@prisma/eclipse";

Usage

Basic Tooltip

The Tooltip component displays helpful information when users hover over or focus on an element.

tsx
import { 
  Tooltip, 
  TooltipContent, 
  TooltipProvider, 
  TooltipTrigger 
} from "@prisma/eclipse";

export function BasicTooltip() {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger>Hover me</TooltipTrigger>
        <TooltipContent>
          <p>This is a helpful tooltip</p>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

Live Example:

<TooltipExample> <div className="flex justify-center p-8"> <Tooltip> <TooltipTrigger asChild> <Button variant="default">Hover me</Button> </TooltipTrigger> <TooltipContent> <p>This is a helpful tooltip</p> </TooltipContent> </Tooltip> </div> </TooltipExample>

With Button Trigger

Use the asChild prop to apply the tooltip to a button component.

tsx
import { 
  Tooltip, 
  TooltipContent, 
  TooltipProvider, 
  TooltipTrigger,
  Button 
} from "@prisma/eclipse";

export function ButtonTooltip() {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger asChild>
          <Button variant="ppg">Deploy</Button>
        </TooltipTrigger>
        <TooltipContent>
          <p>Deploy your application to production</p>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

Live Example:

<TooltipExample> <div className="flex gap-4 justify-center p-8"> <Tooltip> <TooltipTrigger asChild> <Button variant="ppg">Deploy</Button> </TooltipTrigger> <TooltipContent> <p>Deploy your application to production</p> </TooltipContent> </Tooltip> <Tooltip> <TooltipTrigger asChild> <Button variant="orm">Generate</Button> </TooltipTrigger> <TooltipContent> <p>Generate Prisma Client</p> </TooltipContent> </Tooltip> </div> </TooltipExample>

Tooltip Positioning

Control where the tooltip appears using the side prop.

tsx
import { 
  Tooltip, 
  TooltipContent, 
  TooltipProvider, 
  TooltipTrigger,
  Button 
} from "@prisma/eclipse";

export function PositionedTooltips() {
  return (
    <TooltipProvider>
      <div className="flex gap-4">
        <Tooltip>
          <TooltipTrigger asChild>
            <Button>Top</Button>
          </TooltipTrigger>
          <TooltipContent side="top">
            <p>Tooltip on top</p>
          </TooltipContent>
        </Tooltip>

        <Tooltip>
          <TooltipTrigger asChild>
            <Button>Right</Button>
          </TooltipTrigger>
          <TooltipContent side="right">
            <p>Tooltip on right</p>
          </TooltipContent>
        </Tooltip>

        <Tooltip>
          <TooltipTrigger asChild>
            <Button>Bottom</Button>
          </TooltipTrigger>
          <TooltipContent side="bottom">
            <p>Tooltip on bottom</p>
          </TooltipContent>
        </Tooltip>

        <Tooltip>
          <TooltipTrigger asChild>
            <Button>Left</Button>
          </TooltipTrigger>
          <TooltipContent side="left">
            <p>Tooltip on left</p>
          </TooltipContent>
        </Tooltip>
      </div>
    </TooltipProvider>
  );
}

Live Example:

<TooltipExample> <div className="flex gap-4 justify-center p-8"> <Tooltip> <TooltipTrigger asChild> <Button>Top</Button> </TooltipTrigger> <TooltipContent side="top"> <p>Tooltip on top</p> </TooltipContent> </Tooltip> <Tooltip> <TooltipTrigger asChild> <Button>Right</Button> </TooltipTrigger> <TooltipContent side="right"> <p>Tooltip on right</p> </TooltipContent> </Tooltip> <Tooltip> <TooltipTrigger asChild> <Button>Bottom</Button> </TooltipTrigger> <TooltipContent side="bottom"> <p>Tooltip on bottom</p> </TooltipContent> </Tooltip> <Tooltip> <TooltipTrigger asChild> <Button>Left</Button> </TooltipTrigger> <TooltipContent side="left"> <p>Tooltip on left</p> </TooltipContent> </Tooltip> </div> </TooltipExample>

Custom Delay

Control the delay before the tooltip appears using the delayDuration prop on the Tooltip component.

tsx
import { 
  Tooltip, 
  TooltipContent, 
  TooltipProvider, 
  TooltipTrigger,
  Button 
} from "@prisma/eclipse";

export function DelayedTooltip() {
  return (
    <TooltipProvider>
      <Tooltip delayDuration={500}>
        <TooltipTrigger asChild>
          <Button>Hover (500ms delay)</Button>
        </TooltipTrigger>
        <TooltipContent>
          <p>This tooltip has a custom delay</p>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

Live Example:

<TooltipExample> <div className="flex gap-4 justify-center p-8"> <Tooltip delayDuration={0}> <TooltipTrigger asChild> <Button>Instant</Button> </TooltipTrigger> <TooltipContent> <p>No delay (0ms)</p> </TooltipContent> </Tooltip> <Tooltip delayDuration={500}> <TooltipTrigger asChild> <Button>Medium</Button> </TooltipTrigger> <TooltipContent> <p>Medium delay (500ms)</p> </TooltipContent> </Tooltip> <Tooltip delayDuration={1000}> <TooltipTrigger asChild> <Button>Long</Button> </TooltipTrigger> <TooltipContent> <p>Long delay (1000ms)</p> </TooltipContent> </Tooltip> </div> </TooltipExample>

Rich Content

Tooltips can contain rich content including formatted text, links, and icons.

tsx
import { 
  Tooltip, 
  TooltipContent, 
  TooltipProvider, 
  TooltipTrigger,
  Button 
} from "@prisma/eclipse";

export function RichTooltip() {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger asChild>
          <Button variant="ppg">Prisma Accelerate</Button>
        </TooltipTrigger>
        <TooltipContent>
          <div className="space-y-1">
            <p className="font-semibold">Prisma Accelerate</p>
            <p className="text-xs">Global database cache with scalable connection pooling</p>
          </div>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

Live Example:

<TooltipExample> <div className="flex justify-center p-8"> <Tooltip> <TooltipTrigger asChild> <Button variant="ppg">Prisma Accelerate</Button> </TooltipTrigger> <TooltipContent> <div className="space-y-1"> <p className="font-semibold">Prisma Accelerate</p> <p className="text-xs">Global database cache with scalable connection pooling</p> </div> </TooltipContent> </Tooltip> </div> </TooltipExample>

Multiple Tooltips

When using multiple tooltips, wrap them all in a single TooltipProvider for better performance.

tsx
import { 
  Tooltip, 
  TooltipContent, 
  TooltipProvider, 
  TooltipTrigger,
  Button 
} from "@prisma/eclipse";

export function MultipleTooltips() {
  return (
    <TooltipProvider>
      <div className="flex gap-4">
        <Tooltip>
          <TooltipTrigger asChild>
            <Button>Action 1</Button>
          </TooltipTrigger>
          <TooltipContent>
            <p>Tooltip for Action 1</p>
          </TooltipContent>
        </Tooltip>

        <Tooltip>
          <TooltipTrigger asChild>
            <Button>Action 2</Button>
          </TooltipTrigger>
          <TooltipContent>
            <p>Tooltip for Action 2</p>
          </TooltipContent>
        </Tooltip>

        <Tooltip>
          <TooltipTrigger asChild>
            <Button>Action 3</Button>
          </TooltipTrigger>
          <TooltipContent>
            <p>Tooltip for Action 3</p>
          </TooltipContent>
        </Tooltip>
      </div>
    </TooltipProvider>
  );
}

Disabled Elements

When applying tooltips to disabled elements, wrap the element in a span with the tooltip trigger.

tsx
import { 
  Tooltip, 
  TooltipContent, 
  TooltipProvider, 
  TooltipTrigger,
  Button 
} from "@prisma/eclipse";

export function DisabledTooltip() {
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger asChild>
          <span tabIndex={0}>
            <Button disabled>Disabled Action</Button>
          </span>
        </TooltipTrigger>
        <TooltipContent>
          <p>This action is currently unavailable</p>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

Live Example:

<TooltipExample> <div className="flex justify-center p-8"> <Tooltip> <TooltipTrigger asChild> <span tabIndex={0}> <Button disabled>Disabled Action</Button> </span> </TooltipTrigger> <TooltipContent> <p>This action is currently unavailable</p> </TooltipContent> </Tooltip> </div> </TooltipExample>

Component Props

TooltipProvider Props

  • delayDuration - Global delay before tooltips open in milliseconds (number, default: 700)
  • skipDelayDuration - Duration to skip delay when moving between tooltips (number, default: 300)
  • disableHoverableContent - Prevent tooltip from staying open when hovering over content (boolean, default: false)
  • children - Tooltip components (ReactNode, required)

Tooltip Props

  • defaultOpen - Initial open state (boolean, default: false)
  • open - Controlled open state (boolean, optional)
  • onOpenChange - Callback when open state changes (function, optional)
  • delayDuration - Override global delay for this tooltip (number, optional)
  • disableHoverableContent - Override global hoverable content setting (boolean, optional)
  • children - TooltipTrigger and TooltipContent components (ReactNode, required)

TooltipTrigger Props

  • asChild - Merge props onto child element (boolean, default: false)
  • children - Trigger element (ReactNode, required)
  • All standard HTML button attributes when not using asChild

TooltipContent Props

  • side - Preferred side of trigger ("top" | "right" | "bottom" | "left", default: "top")
  • sideOffset - Distance from trigger in pixels (number, default: 4)
  • align - Alignment relative to trigger ("start" | "center" | "end", default: "center")
  • alignOffset - Offset from alignment position (number, default: 0)
  • arrowPadding - Padding between arrow and content edges (number, default: 0)
  • collisionPadding - Padding from viewport edges (number | Partial<Record<Side, number>>, default: 0)
  • sticky - Sticky behavior ("partial" | "always", default: "partial")
  • hideWhenDetached - Hide when trigger is fully occluded (boolean, default: false)
  • className - Additional CSS classes (string, optional)
  • children - Tooltip content (ReactNode, required)

Features

  • ✅ Keyboard accessible with focus states
  • ✅ Automatically positions to avoid viewport edges
  • ✅ Supports hover and focus interactions
  • ✅ Customizable delay and positioning
  • ✅ Rich content support
  • ✅ Smooth animations
  • ✅ Built on Radix UI primitives
  • ✅ Fully typed with TypeScript
  • ✅ Responsive and mobile-friendly
  • ✅ Works with disabled elements

Best Practices

  • Keep content concise - Tooltips should provide brief, helpful information
  • Use for supplementary info - Don't hide critical information in tooltips
  • Wrap in TooltipProvider - Always wrap tooltips in <TooltipProvider> at the root
  • Share provider - Use a single provider for multiple tooltips in the same area
  • Use asChild - Apply asChild prop to trigger when wrapping existing components
  • Accessible text - Ensure tooltip text is concise and descriptive
  • Avoid interactive content - Don't put buttons or links inside tooltips
  • Consider mobile - Tooltips don't work well on touch devices, provide alternative access to info
  • Respect delays - Use appropriate delays (500-700ms) to avoid overwhelming users
  • Positioning - Let tooltips auto-position, but use side when needed
  • Disabled elements - Wrap disabled elements in a span to enable tooltips

Common Use Cases

Icon Buttons

Provide context for icon-only buttons:

tsx
<TooltipProvider>
  <Tooltip>
    <TooltipTrigger asChild>
      <Button size="icon" variant="default">
        <TrashIcon className="h-4 w-4" />
      </Button>
    </TooltipTrigger>
    <TooltipContent>
      <p>Delete item</p>
    </TooltipContent>
  </Tooltip>
</TooltipProvider>

Truncated Text

Show full text for truncated content:

tsx
<TooltipProvider>
  <Tooltip>
    <TooltipTrigger asChild>
      <p className="truncate max-w-xs">
        This is a very long text that will be truncated...
      </p>
    </TooltipTrigger>
    <TooltipContent>
      <p>This is a very long text that will be truncated in the UI</p>
    </TooltipContent>
  </Tooltip>
</TooltipProvider>

Help Icons

Provide contextual help:

tsx
<TooltipProvider>
  <div className="flex items-center gap-2">
    <label>Database URL</label>
    <Tooltip>
      <TooltipTrigger asChild>
        <HelpCircleIcon className="h-4 w-4 text-muted-foreground" />
      </TooltipTrigger>
      <TooltipContent>
        <p>Connection string for your database</p>
      </TooltipContent>
    </Tooltip>
  </div>
</TooltipProvider>

Status Indicators

Explain status states:

tsx
<TooltipProvider>
  <Tooltip>
    <TooltipTrigger asChild>
      <Badge variant="success">Connected</Badge>
    </TooltipTrigger>
    <TooltipContent>
      <p>Database connection is active</p>
    </TooltipContent>
  </Tooltip>
</TooltipProvider>

Accessibility

  • Tooltips are triggered by both hover and keyboard focus
  • Content is announced to screen readers
  • Escape key dismisses open tooltips
  • Tooltips don't trap focus
  • Disabled elements need wrapper span to be keyboard accessible
  • Tooltip content should be brief and descriptive
  • Don't rely solely on tooltips for critical information
  • Color is not the only way to convey information

Provider Configuration

The TooltipProvider should wrap your app or the section containing tooltips:

tsx
// At app root level
export function App() {
  return (
    <TooltipProvider delayDuration={500}>
      <YourApp />
    </TooltipProvider>
  );
}
tsx
// Or at component level
export function Toolbar() {
  return (
    <TooltipProvider>
      <div className="flex gap-2">
      </div>
    </TooltipProvider>
  );
}

Controlled State

For advanced use cases, control the tooltip state:

tsx
import { useState } from "react";

export function ControlledTooltip() {
  const [open, setOpen] = useState(false);

  return (
    <TooltipProvider>
      <Tooltip open={open} onOpenChange={setOpen}>
        <TooltipTrigger asChild>
          <Button>Controlled Tooltip</Button>
        </TooltipTrigger>
        <TooltipContent>
          <p>This tooltip is controlled</p>
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

Integration with Forms

Use tooltips to provide help text for form fields:

tsx
<TooltipProvider>
  <div className="space-y-4">
    <div className="flex items-center gap-2">
      <label htmlFor="username">Username</label>
      <Tooltip>
        <TooltipTrigger asChild>
          <HelpCircleIcon className="h-4 w-4" />
        </TooltipTrigger>
        <TooltipContent>
          <p>Choose a unique username (3-20 characters)</p>
        </TooltipContent>
      </Tooltip>
    </div>
    <input id="username" type="text" />
  </div>
</TooltipProvider>