Primitives
Tooltip
Compact uppercase tooltip.
● LIVE
[ interactive — use the trigger to open ]
"use client";import { Button } from "@/registry/okibi/ui/button";import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,} from "@/registry/okibi/ui/tooltip";export default function TooltipDemo() { return ( <TooltipProvider> <Tooltip> <TooltipTrigger asChild> <Button variant="outline-tech">Ping Sector</Button> </TooltipTrigger> <TooltipContent>SEC // 0x4A2</TooltipContent> </Tooltip> </TooltipProvider> );}npx shadcn@latest add https://okibi.cndr.dev/r/tooltip.jsonInstallation
Install the theme first, then add the component:
npx shadcn@latest add https://okibi.cndr.dev/r/tooltip.jsonInstall the required dependencies:
npm install @radix-ui/react-tooltipCopy the source from the Code tab above into components/ui/tooltip.tsx. It uses the cn helper and the okibi theme tokens — install the theme first if you haven't.
Usage
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip"
<TooltipProvider>
<Tooltip>
<TooltipTrigger>Hover</TooltipTrigger>
<TooltipContent>Transmit packet</TooltipContent>
</Tooltip>
</TooltipProvider>Anatomy
<TooltipProvider> {/* mount ONCE at the app root — shared delay */}
<Tooltip> {/* one trigger/content pair */}
<TooltipTrigger /> {/* the hovered/focused anchor */}
<TooltipContent /> {/* portaled HUD readout */}
</Tooltip>
</TooltipProvider>Examples
Sides
Place tooltips on each side — top, right, bottom, left — all under one shared TooltipProvider.
● LIVE
[ interactive — use the trigger to open ]
"use client";import { Button } from "@/registry/okibi/ui/button";import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,} from "@/registry/okibi/ui/tooltip";export default function TooltipSidesDemo() { return ( <TooltipProvider> <div className="flex flex-wrap items-center gap-3"> <Tooltip> <TooltipTrigger asChild> <Button variant="outline-tech">Top</Button> </TooltipTrigger> <TooltipContent side="top">SIDE // TOP</TooltipContent> </Tooltip> <Tooltip> <TooltipTrigger asChild> <Button variant="outline-tech">Right</Button> </TooltipTrigger> <TooltipContent side="right">SIDE // RIGHT</TooltipContent> </Tooltip> <Tooltip> <TooltipTrigger asChild> <Button variant="outline-tech">Bottom</Button> </TooltipTrigger> <TooltipContent side="bottom">SIDE // BOTTOM</TooltipContent> </Tooltip> <Tooltip> <TooltipTrigger asChild> <Button variant="outline-tech">Left</Button> </TooltipTrigger> <TooltipContent side="left">SIDE // LEFT</TooltipContent> </Tooltip> </div> </TooltipProvider> );}Accessibility
- Radix supplies the
role="tooltip"surface and wires it to the trigger viaaria-describedby. - Opens on hover and on keyboard focus; dismisses on
Escapeor blur — no pointer required. delayDurationdefaults to0for a snappy HUD readout; raise it on the root provider to add a grace period.- Reduced motion is honored globally — the enter/exit fade/zoom/slide is zeroed, so the readout simply appears.
- A tooltip is a supplementary label, not a control — never put interactive elements or essential-only copy inside
TooltipContent.
Guidelines
Do
- Mount ONE
TooltipProvidernear your app root so every tooltip shares a singledelayDurationand grace period. - Give icon-only triggers a real label — wrap the icon in
TooltipTriggerand keep anaria-labelon the control. - Keep the content to a few words: a hint, shortcut, or expanded label.
Don't
- Don't wrap each
Tooltipin its ownTooltipProvider— it works, but it defeats the shared-delay grace period and mis-teaches the pattern. - Don't hide essential information or actions in a tooltip — it's unavailable on touch and to many assistive flows.
- Don't nest buttons, links, or form controls inside
TooltipContent.