apps/eclipse/content/design-system/components/tooltip.mdx
import { Tooltip, TooltipContent, TooltipTrigger, TooltipExample, Button } from "@prisma/eclipse";
The Tooltip component displays helpful information when users hover over or focus on an element.
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>Use the asChild prop to apply the tooltip to a button component.
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>Control where the tooltip appears using the side prop.
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>Control the delay before the tooltip appears using the delayDuration prop on the Tooltip component.
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>Tooltips can contain rich content including formatted text, links, and icons.
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>When using multiple tooltips, wrap them all in a single TooltipProvider for better performance.
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>
);
}
When applying tooltips to disabled elements, wrap the element in a span with the tooltip trigger.
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>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)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)asChild - Merge props onto child element (boolean, default: false)children - Trigger element (ReactNode, required)asChildside - 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)<TooltipProvider> at the rootasChild prop to trigger when wrapping existing componentsside when neededProvide 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>
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>
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>
Explain status states:
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Badge variant="success">Connected</Badge>
</TooltipTrigger>
<TooltipContent>
<p>Database connection is active</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
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">
</div>
</TooltipProvider>
);
}
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>
);
}
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>