Customize components
Tailwind Variants
Nuxt UI components are styled using the Tailwind Variants API, which provides a powerful way to create variants and manage component styles. Let's explore the key features of this API:
Slots
Components in Nuxt UI can have multiple slots, each representing a distinct HTML element or section within the component. These slots allow for flexible content insertion and styling. Let's take the Card component as an example:
export default {
slots: {
root: 'bg-default ring ring-default divide-y divide-default rounded-lg',
header: 'p-4 sm:px-6',
body: 'p-4 sm:p-6',
footer: 'p-4 sm:px-6'
}
}
<template>
<div :class="ui.root({ class: [props.ui?.root, props.class] })">
<div :class="ui.header({ class: props.ui?.header })">
<slot name="header" />
</div>
<div :class="ui.body({ class: props.ui?.body })">
<slot />
</div>
<div :class="ui.footer({ class: props.ui?.footer })">
<slot name="footer" />
</div>
</div>
</template>
Some components don't have slots, they are just composed of a single root element. In this case, the theme only defines the base slot like the Container component for example:
export default {
base: 'max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8'
}
<template>
<div :class="container({ class: props.class })">
<slot />
</div>
</template>
ui prop, only the class prop is available to override styles.Variants
Nuxt UI components use variants to change the slots styles based on props. Here's an example of the Avatar component:
export default {
slots: {
root: 'inline-flex items-center justify-center shrink-0 select-none overflow-hidden rounded-full align-middle bg-elevated',
image: 'h-full w-full rounded-[inherit] object-cover'
},
variants: {
size: {
sm: {
root: 'size-7 text-sm'
},
md: {
root: 'size-8 text-base'
},
lg: {
root: 'size-9 text-lg'
}
}
},
defaultVariants: {
size: 'md'
}
}
This way, the size prop will apply the corresponding styles to the root slot:
<template>
<UAvatar src="https://github.com/nuxt.png" size="lg" />
</template>
The defaultVariants property specifies the default values for each variant. It determines how a component looks and behaves when no prop is provided.
app.config.ts to adjust the standard appearance of components throughout your application.vite.config.ts to adjust the standard appearance of components throughout your application.Customize theme
You have multiple ways to customize the appearance of Nuxt UI components, you can do it for all components at once or on a per-component basis.
tailwind-merge under the hood to merge classes so you don't have to worry about conflicting classes.- Check the
Themesection in the documentation of each individual component. - Browse the source code directly in the GitHub repository at
src/theme.
Config
You can override the theme of components globally inside your app.config.ts by using the exact same structure as the theme object.
Let's say you want to change the font weight of all your buttons, you can do it like this:
export default defineAppConfig({
ui: {
button: {
slots: {
base: 'font-bold'
}
}
}
})
You can override the theme of components globally inside your vite.config.ts by using the exact same structure as the theme object.
Let's say you want to change the font weight of all your buttons, you can do it like this:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
button: {
slots: {
base: 'font-bold'
}
}
}
})
]
})
font-bold class will override the default font-medium class on all buttons.Props
ui prop
You can also override a component's slots using the ui prop. This has priority over the global configuration and variants resolution.
<template>
<UButton
trailing-icon="i-lucide-chevron-right"
size="md"
color="neutral"
variant="outline"
:ui="{
trailingIcon: 'rotate-90 size-3'
}"
>
Button
</UButton>
</template>
trailingIcon slot is overwritten with size-3 even though the md size variant would apply a size-5 class to it.class prop
The class prop allows you to override the classes of the root or base slot. This has priority over the global configuration and variants resolution.
<template>
<UButton class="font-bold rounded-full">Button</UButton>
</template>
font-bold class will override the default font-medium class on this button.