extend prop or the resultant function.The extend prop allows you to extend the component including its variants, slots, defaultVariants and compoundVariants. It automatically merges the values of same keys and offers Typescript autocomplete.
<script lang="ts" setup>
import { uv } from 'unocss-variants';
const baseButton = uv({
base: [
'font-semibold',
'dark:text-white',
'py-1',
'px-3',
'rounded-full',
'active:opacity-80',
'bg-zinc-100',
'hover:bg-zinc-200',
'dark:bg-zinc-800',
'dark:hover:bg-zinc-800',
],
});
const buyButton = uv({
extend: baseButton,
base: [
'text-sm',
'text-white',
'rounded-lg',
'shadow-lg',
'uppercase',
'tracking-wider',
'uno-layer-uv:bg-blue-500',
'uno-layer-uv:hover:bg-blue-600',
'shadow-blue-500/50',
'uno-layer-uv:dark:bg-blue-500',
'uno-layer-uv:dark:hover:bg-blue-600',
],
});
</script>
<template>
<div class="flex gap-3">
<button :class="baseButton()">
Button
</button>
<button :class="buyButton()">
Buy button
</button>
</div>
</template>
/**
* buyButton();
*
* Result:
* font-semibold dark:text-white py-1 px-3 rounded-full active:opacity-80 bg-zinc-100 hover:bg-zinc-200 dark:bg-zinc-800 dark:hover:bg-zinc-800 text-sm text-white rounded-lg shadow-lg uppercase tracking-wider uno-layer-uv:bg-blue-500 uno-layer-uv:hover:bg-blue-600 shadow-blue-500/50 uno-layer-uv:dark:bg-blue-500 uno-layer-uv:dark:hover:bg-blue-600
*/
Components with variants will inherit their variants when composed.
import { uv } from 'unocss-variants';
const baseButton = uv({
base: 'font-semibold text-white rounded-full active:opacity-80',
variants: {
color: {
primary: 'bg-blue-500 hover:bg-blue-700',
secondary: 'bg-purple-500 hover:bg-purple-700',
success: 'bg-green-500 hover:bg-green-700'
},
size: {
small: 'py-0 px-2 text-xs',
medium: 'py-1 px-3 text-sm',
large: 'py-1.5 px-3 text-md'
}
}
});
const myButton = uv({
extend: baseButton,
variants: {
isSquared: {
true: 'rounded-sm'
}
}
// custom button styles
});
myButton({ color: 'success', size: 'medium', isSquared: true });
/**
* Result:
* font-semibold text-white active:opacity-80 rounded-sm bg-purple-500 hover:bg-purple-700 py-1 px-3 text-sm
*/
You can also extend components with defaultVariants and compoundVariants.
import { uv } from 'unocss-variants';
const baseButton = uv({
base: 'font-semibold text-white rounded-full active:opacity-80',
variants: {
color: {
primary: 'bg-blue-500 hover:bg-blue-700',
secondary: 'bg-purple-500 hover:bg-purple-700',
success: 'bg-green-500 hover:bg-green-700'
},
size: {
small: 'py-0 px-2 text-xs',
medium: 'py-1 px-3 text-sm',
large: 'py-1.5 px-3 text-md'
}
},
defaultVariants: {
color: 'primary',
size: 'medium'
},
compoundVariants: [
{
color: 'primary',
size: 'medium',
className: 'rounded-sm'
}
]
});
const myButton = tv({
extend: baseButton
// custom button styles
});
myButton();
/**
* Result:
* font-semibold text-white active:opacity-80 bg-blue-500 hover:bg-blue-700 py-1 px-3 text-sm rounded-sm
*/
You can override any of the inherited variants, defaultVariants and compoundVariants by passing them to the component.
Components with slots will inherit their slots when composed.
<script setup>
import { uv } from 'unocss-variants';
const card = uv({
slots: {
base: 'md:flex bg-slate-100 rounded-xl p-8 md:p-0 dark:bg-gray-900',
avatar:
'w-24 h-24 md:w-48 md:h-auto md:rounded-none rounded-full mx-auto drop-shadow-lg',
wrapper: 'flex-1 pt-6 md:p-8 text-center md:text-left space-y-4',
description: 'text-md font-medium',
infoWrapper: 'font-medium',
name: 'text-sm text-sky-500 dark:text-sky-400',
role: 'text-sm text-slate-700 dark:text-slate-500'
}
});
const myCard = uv({
extend: cardBase
// custom card styles
});
const { base, avatar, wrapper, description, infoWrapper, name, role } = myCard();
</script>
<template>
<figure :class="base()">
<img
:class="avatar()"
src="/intro-avatar.png"
alt=""
width="384"
height="512"
>
<div :class="wrapper()">
<blockquote>
<p :class="description()">
“UnoCSS variants allows you to reduce repeated code in your project
and make it more readable. They fixed the headache of building a
design system with UnoCSS.”
</p>
</blockquote>
<figcaption :class="infoWrapper()">
<div
:class="name()"
>
Zoey Lang
</div>
<div :class="role()">
Full-stack developer, HeroUI
</div>
</figcaption>
</div>
</figure>
</template>
You can override any of the inherited slots by passing a new value to the slot key.
You can use the result of the uv() function to compose your components. However this method is not type-safe and you will have to use the class / className prop to pass the result to the new component.
You can utilize either the base key, slots, or variants when composing components using the result string. The key you use should be in the form of a string array.
import { uv } from 'unocss-variants';
const baseButton = uv({
base: 'font-medium text-sm px-3 py-1 bg-blue-500 text-white rounded-full active:opacity-80'
});
const actionButton = tv({
base: [baseButton(), 'bg-red-500', 'rounded-xs']
});
actionButton();
/**
* Result:
* font-medium text-sm px-3 py-1 text-white active:opacity-80 bg-red-500 rounded-xs
*/
It's important to put the base styles first, so they can be overwritten by the other styles.