Getting Started
Accessibility & reduced motion
The goo is decoration, so it stays out of the way of assistive tech. Reduced motion keeps the goo shape and turns the motion off.
Reduced motion
Every goopUI component honors prefers-reduced-motion: reduce. It doesn't drop the goo. It switches to a still version:
- Kept: the goo body shape and any resting drips. A reduced-motion button still looks like a goopUI button.
- Turned off: the drip simulation, wobble, squish, momentum and flow, reach, taffy, label ride, idle breathing, scroll slosh, splashes, shockwaves, and puddles. This holds for every preset, including
wild. - Oil finish: the sheen holds still.
- State changes: instant, or a short fade.
The engine watches the setting live. If someone turns it on while the page is open, running drips clear and the body snaps back to rest.
You can also force it from your app by setting an attribute on <html>. The engine watches that attribute as well:
document.documentElement.dataset.reducedMotion = 'true'
That's what the switch below does. It also turns off this site's smooth scrolling and scroll reveals, and stops the splashes that fly across the home page.
Per element, attachGoop(el, { reducedMotion: true }) forces the still mode and false ignores the setting. The default, 'auto', follows the OS setting and the attribute.
What stays on, per component
The still version keeps each component's shape and turns off its goo motion.
- Button: the body and resting drips stay. Drips, squish, and shockwaves go.
- Switch, Checkbox, Radio group: the fill and the thumb or dot jump to the new state.
- Slider: the fill and thumbs follow the value. No jelly, slosh, stretch, or splat.
- Progress: the front moves straight to the value. No slosh, wobble, or drips. An indeterminate bar is a still segment.
- Spinner: a still pose of the blobs.
- Popover, Dropdown menu, Tooltip, Tabs: the surface or indicator appears without the ooze, necks, and sloshes.
- Toaster: the toasts keep their goo bodies. No drop in, stretching necks, or drips.
Assistive tech
- The goo layer has
aria-hidden="true"andpointer-events: none. Screen readers, hit-testing, and focus only ever see your real element. - Labels and icons sit above the goo layer, unfiltered, so text stays sharp and keeps its contrast.
- Roles, keyboard handling, and focus management come from reka-ui. They're the same primitives shadcn-vue uses.
- Focus styles come from your theme. The goo doesn't replace or cover your focus ring.
Touch and pointers
- Hover drips only run when
(hover: hover)matches and the pointer is a mouse. A tap on a touch screen never leaves drips running. - Touch and pen get a squish on press and one drip per tap.
- A right click doesn't squish.
- Space and Enter on a focused component give the same squish and shockwave as a click, so keyboard users get the same feedback. Set
keyboard: falseto turn that off. - Escape splashes fly in an overlay that ignores the pointer, so they never block a click.
- Disabled components ignore interaction. Drips already running finish, and nothing new starts.
Layout
Drips never change layout. The goo layer is absolutely positioned and padded outside the element, so content around a dripping button doesn't move.