Getting Started
Installation
Add goopUI to a Nuxt app with the module, or to any Vue 3 app with the package and its stylesheet.
Requirements
- Vue 3.5+ (or Nuxt 3.13+ / Nuxt 4).
- Tailwind CSS v4, already set up in your app (for example with
@tailwindcss/vite). The components are styled with Tailwind utilities, like shadcn's. - The shadcn CSS variables (
--primary,--popover,--radius, and so on). If you already use shadcn-vue, you have them. If not, runnpx shadcn-vue@latest initor copy the variables from the shadcn-vue theming docs. - reka-ui comes with
@goopui/vue(^2.11), so you don't install it yourself. If you also use shadcn-vue, they can share one copy.
Nuxt
Install the module:
pnpm add @goopui/nuxt
Register it:
export default defineNuxtConfig({
modules: ['@goopui/nuxt'],
})
The module auto-imports every component and injects goop.css. Components get the Goop prefix by default, so they sit next to shadcn's without clashing:
<template>
<Button variant="outline">Plain</Button>
<GoopButton>Gooey</GoopButton>
</template>
Change it with the module's prefix option:
export default defineNuxtConfig({
modules: ['@goopui/nuxt'],
goop: { prefix: 'Goo' },
})
Module options
All options go under the goop key and are optional:
| Option | Type | Default | What it does |
|---|---|---|---|
prefix | string | 'Goop' | Prefix for the auto-imported components. '' registers Button, Slider, and so on. |
css | boolean | true | Add @goopui/vue/goop.css to nuxt.options.css. |
tailwindSource | boolean | true | Add an @source for @goopui/vue to every Tailwind v4 entry CSS (any file that imports tailwindcss), so Tailwind generates the classes the components use. Turn it off if you import goop.css from your Tailwind entry yourself. |
preset | 'subtle' | 'playful' | 'wild' | 'playful' | App-wide feel. See Theming. |
renderer | 'svg' | 'canvas' | 'svg' | App-wide renderer. |
finish | 'solid' | 'oil' | 'solid' | App-wide surface finish. |
splash | 'near' | 'escape' | 'off' | 'near' | Where splash and shockwave particles go. |
reducedMotion | boolean | 'auto' | 'auto' | true forces reduced motion on. false ignores the OS setting. |
export default defineNuxtConfig({
modules: ['@goopui/nuxt'],
goop: { prefix: 'Goo', preset: 'subtle' },
})
preset, renderer, finish, splash, and reducedMotion are defaults. A prop on a component beats them. Not every component reads every default. finish and splash only matter to components built on the full drip engine, like Button. The smaller ones (Switch, Slider, Progress, ...) read preset, renderer, and reducedMotion, and the Toaster reads preset and reducedMotion.
The Toaster
GoopToaster wraps vue-sonner, which is a peer dependency. Install it and add its stylesheet only if you use the Toaster. See the Toaster page.
pnpm add vue-sonner
Vue
Install the package:
pnpm add @goopui/vue
Import the stylesheet after Tailwind. It holds the --goop-* tokens, the keyframes, and an @source so Tailwind picks up the classes the components use:
@import "tailwindcss";
@import "@goopui/vue/goop.css";
Then import components where you use them:
<script setup lang="ts">
import { GoopButton } from '@goopui/vue'
</script>
<template>
<GoopButton>Gooey</GoopButton>
</template>
To set app-wide defaults, install the plugin. They take the same values as the Nuxt module options above:
import { createApp } from 'vue'
import { GoopPlugin } from '@goopui/vue'
import App from './App.vue'
createApp(App).use(GoopPlugin, { preset: 'subtle' }).mount('#app')
To set them for one part of the tree, call provideGoopConfig({ preset: 'wild' }) in a parent component.
@goopui/vue depends on reka-ui and @goopui/core, so you don't install those yourself. vue is a peer dependency, and so is vue-sonner if you use the Toaster:
pnpm add vue-sonner
@import "vue-sonner/style.css";
Versions
All @goopui/* packages are released together with the same version number. Keep them in step:
pnpm up "@goopui/*"
Components
Components are named with the Goop prefix and keep the shadcn-vue API. The full list is on the introduction page. Each component has its own page with a live demo and its props.
React and Svelte
They're coming after the Vue API settles. Until then you can use @goopui/core directly. It works on any element.