Tooltip
A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.
Usage
Basic Tooltip
The Tooltip component displays helpful information when users hover over or focus on an element.
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger
} from "@prisma-docs/eclipse";
export function BasicTooltip() {
return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger>Hover me</TooltipTrigger>
<TooltipContent>
<p>This is a helpful tooltip</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
}Live Example:
With Button Trigger
Use the asChild prop to apply the tooltip to a button component.
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
Button
} from "@prisma-docs/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:
Tooltip Positioning
Control where the tooltip appears using the side prop.
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
Button
} from "@prisma-docs/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:
Custom Delay
Control the delay before the tooltip appears using the delayDuration prop on the Tooltip component.
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
Button
} from "@prisma-docs/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:
Rich Content
Tooltips can contain rich content including formatted text, links, and icons.
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
Button
} from "@prisma-docs/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:
Multiple Tooltips
When using multiple tooltips, wrap them all in a single TooltipProvider for better performance.
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
Button
} from "@prisma-docs/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.
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
Button
} from "@prisma-docs/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:
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
asChildprop 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
sidewhen needed - Disabled elements - Wrap disabled elements in a span to enable tooltips
Common Use Cases
Icon Buttons
Provide context for icon-only buttons:
<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:
<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:
<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:
<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:
// At app root level
export function App() {
return (
<TooltipProvider delayDuration={500}>
<YourApp />
</TooltipProvider>
);
}// Or at component level
export function Toolbar() {
return (
<TooltipProvider>
<div className="flex gap-2">
{/* Multiple tooltips here */}
</div>
</TooltipProvider>
);
}Controlled State
For advanced use cases, control the tooltip state:
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:
<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>