Checkbox

Components

Checkbox

shadcn's Checkbox where checking drops goo into the box. It splats, splashes, and sucks back up when you uncheck.

Click, or Tab to a box and press Space.

Customize

Preset
Colour
Speed 1.00×

GoopCheckbox wraps reka-ui's CheckboxRoot and CheckboxIndicator, the same primitive as shadcn-vue's Checkbox, with the same API and classes. v-model (including 'indeterminate'), disabled, name, required, value, asChild, keyboard handling, and role="checkbox" all come from reka-ui. The goo is a layer inside the box.

Installation

Install @goopui/nuxt or @goopui/vue as shown on the Button page. The Nuxt module auto-imports GoopCheckbox. It uses the same shadcn tokens as the plain Checkbox (--primary, --primary-foreground, --input, --ring).

Usage

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

const terms = ref(false)
</script>

<template>
  <label class="flex items-center gap-2 text-sm">
    <GoopCheckbox v-model="terms" />
    Accept terms and conditions
  </label>
</template>

What it does

  • Checking. A drop falls into the box from above, stretched along its fall. On impact the fill swells out of it and splats flat against the floor, then wobbles. A few droplets splash out sideways. The check mark appears once the splat has mostly settled.
  • Unchecking. The fill sucks up into a drop above the box on a neck. The neck snaps, and the drop swells and pops into specks.
  • Indeterminate. A goo bar stretches across the middle and wobbles. From checked, the fill drains into it.

The check mark is the same unfiltered icon as shadcn's, so it stays sharp. It is only held back until the goo lands.

Indeterminate

v-model takes true, false, or 'indeterminate', as in reka-ui:

Click to cycle: indeterminate, checked, unchecked.
<script setup lang="ts">
import type { CheckboxState } from '@goopui/core'

const all = ref<CheckboxState>('indeterminate')
</script>

<template>
  <GoopCheckbox v-model="all" />
</template>

Effects and presets

Every effect is a prop. false turns it off, true uses the preset's strength, and a number scales it (0 is off). fill is on or off only.

<GoopCheckbox :splat="false" />
<GoopCheckbox :droplets="false" />
<GoopCheckbox preset="wild" />
<GoopCheckbox :speed="0.5" />

Disabled and goo off

<GoopCheckbox disabled />
<GoopCheckbox disabled default-value />
<GoopCheckbox :goo="false" />

Colors

The fill and droplets use the --goop-checkbox-fill variable, which defaults to var(--primary), the color shadcn fills a checked box with. Override it on the element or an ancestor:

<GoopCheckbox class="[--goop-checkbox-fill:var(--color-emerald-500)] data-checked:border-emerald-500" />

Props

GoopCheckbox keeps the shadcn-vue Checkbox API and adds the goo props.

GoopCheckbox props
PropTypeDefaultNotes
modelValueboolean | 'indeterminate'The controlled state (v-model).
defaultValueboolean | 'indeterminate'falseThe initial state when uncontrolled.
disabledbooleanfalse
id, name, value, requiredPassed to reka-ui. name and value make it submit with a form.
asChild, asThe element to render, via reka-ui.
classstring | array | objectMerged onto the box.
goobooleantrueMaster switch. false renders a plain shadcn Checkbox.
fillboolean | numbertrueThe check fills the box with goo instead of a flat colour.
splatboolean | numbertrueThe goo splats into the box on check and wobbles to rest.
dropletsboolean | numbertrueA few droplets fly off on impact and fall back.
speednumber1Speed multiplier.
preset'subtle' | 'playful' | 'wild'app config, then playfulThe feel.
renderer'svg' | 'canvas''svg'How the goo is drawn.

The default slot replaces the check mark. It receives reka-ui's slot props. GoopCheckbox also exposes handle (the live checkbox handle, null before mount or with goo off) and el (the box).

Before it mounts, during SSR, and with :goo="false", it is a plain shadcn Checkbox, so first paint and hydration match.

Accessibility

It's a real reka-ui checkbox: role="checkbox", aria-checked (mixed when indeterminate), focus ring, Space to toggle. The goo layer is aria-hidden and can't be clicked.

Reduced motion keeps the goo shape and turns off the simulation: the box fills, or shows its bar, straight away, with no drop, splat, droplets, or suck-up. See Accessibility & reduced motion.