Tooltip
A small floating label that appears above an element on hover or focus.
A hover bubble. It is a hint, never the only place information lives — a control whose meaning is only in its tooltip is a control with no accessible name.
newt-tooltipimport {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/registry/bases/newt/ui/tooltip"
export default function TooltipDemo() {
return (
<Tooltip>
<TooltipTrigger>
<button
type="button"
aria-describedby="tooltip-example"
className="inline-flex h-8 w-8 items-center justify-center rounded-full bg-newt-bg-elevated text-sm font-medium text-newt-text-secondary transition-colors duration-fast ease-newt hover:bg-newt-bg-hover hover:text-newt-text-primary"
>
?
</button>
</TooltipTrigger>
<TooltipContent id="tooltip-example">Tooltip text</TooltipContent>
</Tooltip>
)
}<script setup lang="ts">
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "~~/registry/bases/newt/ui/tooltip"
</script>
<template>
<Tooltip>
<TooltipTrigger>
<button
type="button"
aria-describedby="tooltip-example"
class="inline-flex h-8 w-8 items-center justify-center rounded-full bg-newt-bg-elevated text-sm font-medium text-newt-text-secondary transition-colors duration-fast ease-newt hover:bg-newt-bg-hover hover:text-newt-text-primary"
>
?
</button>
</TooltipTrigger>
<TooltipContent id="tooltip-example">Tooltip text</TooltipContent>
</Tooltip>
</template>Installation
pnpm dlx newtui@latest add tooltipnpx newtui@latest add tooltipyarn dlx newtui@latest add tooltipbunx newtui@latest add tooltipCopy the source into your project
import * as React from "react"
import { cn } from "@/lib/utils"
const Tooltip = React.forwardRef<
HTMLSpanElement,
React.HTMLAttributes<HTMLSpanElement>
>(({ className, ...props }, ref) => (
<span
ref={ref}
className={cn("group relative inline-flex", className)}
{...props}
/>
))
Tooltip.displayName = "Tooltip"
const TooltipTrigger = React.forwardRef<
HTMLSpanElement,
React.HTMLAttributes<HTMLSpanElement>
>(({ className, ...props }, ref) => (
<span ref={ref} className={cn("inline-flex", className)} {...props} />
))
TooltipTrigger.displayName = "TooltipTrigger"
const TooltipContent = React.forwardRef<
HTMLSpanElement,
React.HTMLAttributes<HTMLSpanElement>
>(({ className, ...props }, ref) => (
<span
ref={ref}
role="tooltip"
className={cn(
"pointer-events-none absolute bottom-[calc(100%+8px)] start-1/2 -translate-x-1/2 whitespace-nowrap rounded-sm bg-[#111214] px-2.5 py-1.5 text-xs font-medium text-newt-text-primary opacity-0 shadow-elevation-high transition-opacity duration-fast ease-newt group-hover:opacity-100 group-focus-within:opacity-100",
className
)}
{...props}
/>
))
TooltipContent.displayName = "TooltipContent"
export { Tooltip, TooltipTrigger, TooltipContent }<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/lib/utils"
const props = defineProps<{ class?: HTMLAttributes["class"] }>()
</script>
<template>
<span :class="cn('group relative inline-flex', props.class)">
<slot />
</span>
</template><script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/lib/utils"
const props = defineProps<{ class?: HTMLAttributes["class"] }>()
</script>
<template>
<span :class="cn('inline-flex', props.class)">
<slot />
</span>
</template><script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { cn } from "@/lib/utils"
const props = defineProps<{ class?: HTMLAttributes["class"] }>()
</script>
<template>
<span
role="tooltip"
:class="
cn(
'pointer-events-none absolute bottom-[calc(100%+8px)] start-1/2 -translate-x-1/2 whitespace-nowrap rounded-sm bg-[#111214] px-2.5 py-1.5 text-xs font-medium text-newt-text-primary opacity-0 shadow-elevation-high transition-opacity duration-fast ease-newt group-hover:opacity-100 group-focus-within:opacity-100',
props.class
)
"
>
<slot />
</span>
</template>export { default as Tooltip } from "./Tooltip.vue"
export { default as TooltipTrigger } from "./TooltipTrigger.vue"
export { default as TooltipContent } from "./TooltipContent.vue"Update the import paths
The files import @/lib/utils and sibling components through the aliases in your components.json. Point them at wherever those live in your project.
Usage
import { Tooltip } from "@/components/ui/tooltip"
export function Example() {
return <Tooltip />
}<script setup lang="ts">
import { Tooltip, TooltipTrigger, TooltipContent } from "@/components/ui/tooltip"
</script>
<template>
<Tooltip />
</template>API reference
Tooltip
content?ReactNode
What the bubble says.
ReactNodeside?"top" | "right" | "bottom" | "left"
Preferred side. Flips when there is no room.
"top" | "right" | "bottom" | "left""top"Every part also accepts the native attributes of the element it renders, and a className that is merged rather than replaced.
Accessibility
The bubble is linked to its trigger with aria-describedby, so it is read as a description rather than as the name. It opens on focus as well as hover, and Escape dismisses it. Do not put a control inside a tooltip: it cannot be reached by keyboard.
Tokens
Tooltip reads its colours, radii and motion from the --newt-* tokens installed with the library. Override a token and every component that reads it follows, including this one — see the token layer. In the plain HTML and CSS distribution the same component is newt-tooltip.