Progress

Components

Progress

shadcn's Progress that fills like liquid. The front bulges when the value changes, and a drip falls now and then.

35%
Use the buttons to step the value.

Customize

Preset
Colour
Speed 1.00×

Installation

Nuxt

pnpm add @goopui/nuxt
nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@goopui/nuxt'],
})

The module auto-imports GoopProgress and adds goop.css. See Installation for the module options.

Vue

pnpm add @goopui/vue
main.css
@import "tailwindcss";
@import "@goopui/vue/goop.css";

Usage

GoopProgress wraps the same reka-ui Progress as shadcn-vue's Progress. The API is the same: v-model is a number from 0 to max (default 100), and reka-ui keeps role="progressbar" and the ARIA values.

<script setup lang="ts">
// Nuxt auto-imports this. In plain Vue, import it:
import { GoopProgress } from '@goopui/vue'

const progress = ref(35)
</script>

<template>
  <GoopProgress v-model="progress" />
</template>

Behavior

  • Front. The leading edge is a rounded blob that chases the value on a soft spring and stretches with its speed. It bulges and wobbles each time the value changes (wobble).
  • Slosh. The top surface of the fill carries a slow wave. It piles up toward the front when the fill speeds up and sloshes back when it stops (slosh).
  • Drips. Now and then a drop swells on the underside of the front, necks off, and falls (drips). At most three at once. The bar is a thin strip, so the drops are drawn in the goo layer around it and never change layout.
  • Layout never changes. The goo is drawn in one aria-hidden layer on the root. The real indicator stays in place and goes see-through.

Auto-updating

The fill follows whatever value you give it, so bursty updates look best. This one fills in uneven bursts, holds at 100, and starts over:

0%
<GoopProgress :model-value="progress" />

Taller bars

The goo follows the root's box, so a taller bar has more room for the front and the drips. Set the height with class:

<GoopProgress :model-value="65" class="h-3" />

Indeterminate

Pass null when you don't know the value. A goo slug runs along the bar with the same surge as GoopSpinner, stretching when it's fast, and it drips too.

<GoopProgress :model-value="null" />
<GoopProgress :model-value="null" class="h-3" />

Color

The goo is painted in --primary. To change it, set --goop-progress-color on the bar or any ancestor:

<GoopProgress :model-value="60" class="[--goop-progress-color:var(--destructive)]" />

The track keeps shadcn's bg-muted. Style it with class as you would in shadcn. Use :goo="false" to render a plain shadcn Progress.

Props

GoopProgress keeps the shadcn-vue Progress API and adds the goo props.

GoopProgress props
PropTypeDefaultNotes
modelValuenumber | null0The value (v-model). null is indeterminate.
maxnumber100The value that means full.
getValueLabel, getValueText(value, max) => stringPassed to reka-ui, for the ARIA value text.
as, asChildRender a different element.
classstring | array | objectMerged onto the root, like shadcn.
goobooleantrueMaster switch. false renders a plain shadcn Progress.
sloshboolean | numbertrueThe top surface waves, piles up toward the front, and sloshes back.
dripsboolean | numbertrueDrops form on the front's underside now and then and fall.
wobbleboolean | numbertrueThe front bulges and wobbles when the value changes.
seednumber0Varies drip timing and sizes, so two bars don't drip in step.
speednumber1Animation speed multiplier.
preset'subtle' | 'playful' | 'wild''playful'The feel. Falls back to the app config, then --goop-preset.
renderer'svg' | 'canvas''svg'How the goo is drawn.

Effect props take true, false, or a number from 0 to 2. Props win over the app-wide config (GoopPlugin or the module options), which wins over the preset.

GoopProgress also exposes handle (the core handle, null before mount or with goo off) and el.

Accessibility

It's a real reka-ui progress bar: role="progressbar" with aria-valuenow, aria-valuemin, and aria-valuemax, and no value attributes when indeterminate. Pass aria-label (it lands on the root) so the bar has a name. The goo layer is aria-hidden. Under reduced motion the goo keeps its shape and the effects turn off: the front moves straight to the value, there's no slosh, wobble, or drips, and the indeterminate slug sits still in the middle of the bar. See Accessibility & reduced motion.