Framework usage

Use the class string from uv() with Vue, React, Svelte, Solid, Angular, or vanilla DOM.

uv is framework-agnostic. It returns a string (or slot functions that return strings). Bind that string to whatever the host calls “class”.

import { uv } from 'unocss-variants';

const button = uv({
  base: 'inline-flex cursor-pointer items-center justify-center rounded-md px-4 py-2 text-sm font-medium select-none',
  variants: {
    color: {
      primary: 'bg-blue-600 color-white',
      secondary: 'bg-zinc-200 color-zinc-900'
    }
  },
  defaultVariants: {
    color: 'primary'
  }
});

Both class and className work as override keys on the recipe (and on each slot function). Pick the one that matches the framework so you can forward the host prop through.

<script setup>
import { uv } from 'unocss-variants';

const button = uv({
  base: 'inline-flex items-center rounded-md px-4 py-2 text-sm font-medium',
  variants: {
    color: {
      primary: 'bg-blue-600 color-white',
      secondary: 'bg-zinc-200 color-zinc-900'
    }
  }
});
</script>

<template>
  <button :class="button({ color: 'primary' })">
    Save
  </button>
</template>

Pass a Vue class prop through with the class override:

button({ color: 'primary', class: props.class });

Slotted recipes

When the recipe defines slots, the call returns an object of functions instead of a string. Destructure the parts you need:

<script setup>
const { base, title, description } = alert({ color: 'danger' });
</script>

<template>
  <div :class="base()">
    <p :class="title()">
      Title
    </p>
    <p :class="description()">
      Body
    </p>
  </div>
</template>

In React, use className on the slot functions:

const { base, title } = alert({ color: 'danger' });

return (
  <div className={base()}>
    <p className={title()}>Title</p>
  </div>
);

See Slots.