Tooltip
Hover and focus hints for icon buttons, keyboard shortcuts, and truncated labels — with the neobrutalist border-and-shadow treatment.
import { Button } from "@/components/ui/button"
import {
Tooltip,The tooltip is a short label that appears on hover or keyboard focus and describes the control it wraps — supplemental text, never a place for interactive content. Built on the Base UI Tooltip primitive, portalled and collision-aware, and styled to the neobrutalist recipe: thick border, hard shadow, and an inverted fill so it reads on any background.
Reach for it when:
- Icon-only buttons — name the action a bare icon can't: toolbars, table row actions, editor controls.
- Keyboard shortcuts — spell out the binding next to the label with
Kbd, as in the example below. - Truncated or terse text — full file names, clipped table cells, abbreviated status codes.
Installation#
Run the following command:
pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/tooltip.jsonnpx shadcn@latest add https://neobrutalism.com/r/base/tooltip.jsonyarn dlx shadcn@latest add https://neobrutalism.com/r/base/tooltip.jsonbunx --bun shadcn@latest add https://neobrutalism.com/r/base/tooltip.json
Add the TooltipProvider to the root of your app.
import { TooltipProvider } from "@/components/ui/tooltip"
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<TooltipProvider>{children}</TooltipProvider>
</body>
</html>
)
}Install the following dependencies:
pnpm add @base-ui/reactnpm install @base-ui/reactyarn add @base-ui/reactbun add @base-ui/react
Copy and paste the following code into your project.
"use client"
import * as React from "react"
import { Tooltip as TooltipPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
function TooltipProvider({
delayDuration = 0,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
return (
<TooltipPrimitive.Provider
data-slot="tooltip-provider"
delayDuration={delayDuration}
{...props}
/>
)
}
function Tooltip({
...props
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
}
function TooltipTrigger({
...props
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
}
function TooltipContent({
className,
sideOffset = 0,
children,
...props
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
return (
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
data-slot="tooltip-content"
sideOffset={sideOffset}
className={cn(
"z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded border-2 bg-foreground px-2 py-1 text-xs text-background shadow-md has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
className
)}
{...props}
>
{children}
<TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" />
</TooltipPrimitive.Content>
</TooltipPrimitive.Portal>
)
}
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }
Update the import paths to match your project setup.
Add the TooltipProvider to the root of your app.
import { TooltipProvider } from "@/components/ui/tooltip"
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<TooltipProvider>{children}</TooltipProvider>
</body>
</html>
)
}Usage#
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip"<Tooltip>
<TooltipTrigger>Hover</TooltipTrigger>
<TooltipContent>
<p>Add to library</p>
</TooltipContent>
</Tooltip>Composition#
Use the following composition to build a Tooltip:
Tooltip
├── TooltipTrigger
└── TooltipContentExamples#
Side#
Use the side prop to change the position of the tooltip.
import { Button } from "@/components/ui/button"
import {
Tooltip,With Keyboard Shortcut#
import { SaveIcon } from "lucide-react"
import { Button } from "@/components/ui/button"Disabled Button#
Show a tooltip on a disabled button by wrapping it with a span.
import { Button } from "@/components/ui/button"
import {
Tooltip,RTL#
To enable RTL support in Neobrutalism.com, see the RTL configuration guide.
"use client"
import {Accessibility#
The tooltip follows the WAI-ARIA Tooltip pattern: the popup renders with role="tooltip" and the primitive points the trigger's aria-describedby at it, so screen readers announce the hint as a description of the control. The tooltip itself never takes focus — put links or buttons in a Popover instead, and keep the trigger understandable without it.
Keyboard interactions:
| Key | Action |
|---|---|
Tab / Shift + Tab | Move focus to the trigger — focusing opens the tooltip, leaving closes it |
Escape | Dismiss the tooltip while focus stays on the trigger |
Enter / Space | Activate the trigger's own action — the tooltip is a description, not a control |
API Reference#
See the Base UI Tooltip documentation.