TooltipDesign system
ComponentProduct

Tooltip

Short label shown on hover or keyboard focus, with a shared delay between adjacent controls.

npx context-ds add tooltip
In the product

Usage

Use it for

Naming icon buttons and explaining truncated values; wrap for a sentence-long label.

Avoid

  • Essential information only in a tooltip
  • Long paragraphs

Dependencies: surface, tooltip-provider, @radix-ui/react-tooltip

Example

examples/tooltip.tsx
"use client";import { useState } from "react";import { useCopy } from "@/components/ui/copy-button";import { Copy, Info } from "lucide-react";import { Button } from "@/components/ui/button";import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";// A one-line label naming an icon button, and a `wrap` label explaining a value. They wait a beat// on hover or focus, then the neighbors appear at once.export function Product() {  const { copy, hasCopied } = useCopy();  const [open, setOpen] = useState(false);  return (    <div className="flex items-center gap-16 pt-8 pb-4">      <Tooltip>        <TooltipTrigger asChild>          <Button variant="ghost" size="icon" aria-label={hasCopied ? "Copied" : "Copy key"} onClick={() => copy("ctx_example_key")}>            <Copy strokeWidth={1.5} />          </Button>        </TooltipTrigger>        <TooltipContent side="top">{hasCopied ? "Copied" : "Copy key"}</TooltipContent>      </Tooltip>      <Tooltip open={open} onOpenChange={setOpen}>        <TooltipTrigger asChild>          <Button variant="ghost" size="icon" aria-label="About credits" onClick={(event) => { event.preventDefault(); setOpen(true); }}>            <Info strokeWidth={1.5} />          </Button>        </TooltipTrigger>        <TooltipContent side="right" wrap>          Credits reset on the first of each month. Unused credits do not roll over.        </TooltipContent>      </Tooltip>    </div>  );}

Source

components/ui/tooltip.tsx
"use client";import * as React from "react";import * as TooltipPrimitive from "@radix-ui/react-tooltip";import { usePortalContainer } from "@/lib/surface";import { TooltipProvider, useTooltipScope } from "@/lib/tooltip-provider";import { cn } from "@/lib/utils";// Hovering waits a beat before the label appears, so passing over a control doesn't flash it; once one is showing,// the next one within the warm window appears at once (Radix's skip delay), so sweeping a row of icons doesn't wait.function Tooltip(props: React.ComponentProps<typeof TooltipPrimitive.Root>) {  const shared = useTooltipScope();  if (shared) return <TooltipPrimitive.Root data-slot="tooltip" {...props} />;  return (    <TooltipProvider>      <TooltipPrimitive.Root data-slot="tooltip" {...props} />    </TooltipProvider>  );}function TooltipTrigger(props: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {  return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;}// The dashboard's label: white, control corners, 11px on a hairline and a soft shadow, on one line unless `wrap`, 6px// above (or 8px beside) its trigger. The first one hovered grows from its trigger in a short ease-out pop; the next ones// in the warm window (Radix's instant open) appear at once. Reduced motion keeps only the fade.function TooltipContent({ className, side = "right", sideOffset, wrap = false, children, ...props }: React.ComponentProps<typeof TooltipPrimitive.Content> & { wrap?: boolean }) {  return (    <TooltipPrimitive.Portal container={usePortalContainer()}>      <TooltipPrimitive.Content        data-slot="tooltip-content"        side={side}        sideOffset={sideOffset ?? (side === "left" || side === "right" ? 8 : 6)}        className={cn(          "z-50 origin-(--radix-tooltip-content-transform-origin) rounded-control bg-surface px-2 py-1 text-axis leading-4 text-fg shadow-tooltip data-[state=delayed-open]:animate-pop-in",          wrap ? "w-max max-w-64 text-pretty" : "whitespace-nowrap",          className,        )}        {...props}      >        {children}      </TooltipPrimitive.Content>    </TooltipPrimitive.Portal>  );}export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };

Reference: context-dashboard c0ddf7a src/components/ui/tooltip.tsx.