Components
Tooltip
shadcn's Tooltip with goo. A small label that blooms open, quick and light.
Customize
GoopTooltip wraps the same reka-ui Tooltip primitive as shadcn-vue's Tooltip, with the same API. Delays, hover and focus handling, and positioning work the same. Swap the imports and you're done.
Installation
Nuxt
pnpm add @goopui/nuxt
export default defineNuxtConfig({
modules: ['@goopui/nuxt'],
})
The module auto-imports every GoopTooltip* part, adds goop.css, and points Tailwind at the component classes. It needs Tailwind CSS v4 and the shadcn tokens (--foreground, --background, --radius).
Vue
pnpm add @goopui/vue
@import "tailwindcss";
@import "@goopui/vue/goop.css";
Usage
Wrap your app (or the part that has tooltips) in a GoopTooltipProvider once. It sets delayDuration to 0, like shadcn.
<script setup lang="ts">
// Nuxt auto-imports these. In plain Vue, import them:
import { GoopButton, GoopTooltip, GoopTooltipContent, GoopTooltipProvider, GoopTooltipTrigger } from '@goopui/vue'
</script>
<template>
<GoopTooltipProvider>
<GoopTooltip>
<GoopTooltipTrigger as-child>
<GoopButton variant="outline">Hover me</GoopButton>
</GoopTooltipTrigger>
<GoopTooltipContent>Add to library</GoopTooltipContent>
</GoopTooltip>
</GoopTooltipProvider>
</template>
The parts are GoopTooltipProvider, GoopTooltip, GoopTooltipTrigger, and GoopTooltipContent. All the goo lives on GoopTooltipContent.
Behavior
It's the Popover's emerge engine, scaled down for a small label:
- Open (bloom). The label pools from its own center, spreads out with a lobed edge, overshoots, and settles. It's quick: about a third of a second at the default preset.
- Light slosh. The edges bulge a little and settle (
openSlosh, 0.4 strength by default). - Light splash. A few small drops fly off and keep clear of the trigger. It's much lighter than the Popover's (
openDrips, and theopenDrip*knobs to turn it up). - Close. The label pulls in with a light wobble (
closeSlosh, 0.5) and shrinks back to its center.
flowStyle="neck" runs it out of the trigger through a neck instead. :flow="false" gives the older open: a small bulb swells out of the trigger edge, the label inflates out of it, and the neck snaps. That open has no drips unless you turn openDrips on.
- Text stays sharp. Only the background is goo, drawn behind the label.
Inverted tokens
Like shadcn's tooltip, it's inverted: a --foreground background with --background text. That is the default here too, and the arrow matches. A tooltip is a label, not an extension of its trigger, so unlike the Popover the default surface is 'popover' (shadcn's inverted look), not 'trigger'.
Sides
side, align, and sideOffset are reka-ui's:
<GoopTooltipContent side="right">Tooltip on the right</GoopTooltipContent>
Surface color and drips
Set surface="trigger" to use the trigger's background and text color, or pass any CSS color. The text and the arrow follow. :open-drips sets the splash:
<GoopTooltipContent surface="trigger">Takes the trigger's color</GoopTooltipContent>
<GoopTooltipContent surface="oklch(0.62 0.19 150)">Any CSS color</GoopTooltipContent>
<GoopTooltipContent :open-drips="false">No splash</GoopTooltipContent>
<GoopTooltipContent :open-drips="1.5">A bigger splash</GoopTooltipContent>
Plain shadcn
:goo="false" renders exactly shadcn's TooltipContent, with its own enter and exit animation.
Driving it from code
GoopTooltipContent exposes its engine handle as handle (null before it mounts, or when goo is off).
Props
GoopTooltipProvider, GoopTooltip, and GoopTooltipTrigger take shadcn-vue's props. GoopTooltipContent takes reka-ui's TooltipContent props (side, align, sideOffset, ...), class, and these goo props. sideOffset defaults to 0, like shadcn.
| Prop | Type | Default | Notes |
|---|---|---|---|
goo | boolean | true | Master switch. false renders a plain shadcn TooltipContent. |
flow | boolean | true | Flow open, in flowStyle. false: the tooltip inflates from a small bulb at the trigger edge (bridge and momentum apply, no drips by default). |
flowStyle | 'bloom' | 'neck' | 'bloom' | 'bloom' pools from the tooltip's own center, spreads out with a lobed edge, overshoots, and settles. 'neck' runs out of the trigger through a thick neck. |
bloomStart | 'single' | 'merge' | 'single' | How the bloom starts: one droplet swells, or a few drops fuse. |
bridge | boolean | true | A small bulb and lumpy neck between the trigger and the tooltip. Not used by bloom. |
wobble | boolean | true | Jelly overshoot and wobble (bloom: the open overshoot and settle). |
momentum | boolean | true | The tooltip launches away from the trigger, stretching the neck until it snaps. Not used by bloom. |
fade | boolean | true | The text (and the arrow) fades in once the goo settles. |
openSlosh | boolean | number | true (0.4) | On open, the far edge (bloom: every edge) bulges and wobbles. true is a light 0.4; a number from 0 to 2 sets the strength. |
openDrips | boolean | number | bloom: on (light); bulb: false | Bloom: a light splash of a few small drops that keep off the trigger. false turns it off; a number from 0 to 2 or the openDrip* knobs turn it up. With flow off, drops are off unless you turn them on. |
openDripAmount | number | 1 (bloom 0.3) | Drop count, 0 to 3. |
openDripSize | number | 1 (bloom 0.6) | Drop size, 0.3 to 2.5. |
openDripFling | number | 1 (bloom 0.6) | How far the drops are flung, 0 to 3. |
openDripVariety | number | 0.7 | Mix of globs and specks, 0 to 1. |
sloshVariety | number | 1 | How differently each side bulges on open and sloshes on close (off-centre, one or two lumps, staggered; re-rolled every open), 0 to 1. 0 is an even, centred bulge. |
closeSlosh | boolean | number | true (0.5) | On close, the near edge sloshes against the trigger (bloom: the inward pull and wobble before it shrinks to the center). true is a light 0.5; a number from 0 to 2 sets the strength. |
surface | 'popover' | 'trigger' | string | 'popover' | 'popover' is shadcn's inverted tooltip (foreground goo, background text). 'trigger' takes the trigger's background and text color. Any CSS color works, and the arrow follows. |
speed | number | 1 | Animation speed multiplier. |
preset | 'subtle' | 'playful' | 'wild' | app config, then playful | The overall feel. |
renderer | 'svg' | 'canvas' | 'svg' | How the goo is drawn. |
side | 'top' | 'right' | 'bottom' | 'left' | 'top' | The side of the trigger it opens on (reka-ui). |
Accessibility
Hover and keyboard focus open it, Escape closes it, and the content has role="tooltip" and is linked to the trigger, all from reka-ui. The goo surface is aria-hidden. Under reduced motion the tooltip opens and closes plainly: it keeps its goo shape and color, with no bloom, bridge, slosh, drops, or wobble. See Accessibility & reduced motion.