自定义组件
Tailwind Variants
Nuxt UI 组件使用 Tailwind Variants API 进行样式设置,该 API 提供了一种创建变体和管理组件样式的强大方式。
插槽
组件可以拥有多个 slots(插槽),每个插槽代表组件内不同的 HTML 元素或部分。这些插槽允许灵活的内容插入和样式自定义。
以具有多个插槽的 Card 组件为例:
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>
有些组件没有插槽,仅由单个根元素组成。在这种情况下,主题仅定义 base 插槽,例如 Container 组件。
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>
变体 (Variants)
组件支持 variants,允许你根据组件属性动态调整不同 slots 的样式。
例如,Avatar 组件使用 size 变体来控制其外观。
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'
}
}
这样,size 属性会将相应的样式应用于 root 插槽。
<template>
<UAvatar src="https://github.com/nuxt.png" size="lg" />
</template>
默认变体 (Default Variants)
defaultVariants 属性用于设置当未传入属性时,每个变体的默认值。
例如,Avatar 组件的默认大小设置为 md。
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'
}
}
复合变体 (Compound Variants)
某些组件使用 compoundVariants 属性,以便在同时满足多个变体条件时应用样式类。
例如,Button 组件使用 compoundVariants 属性来为特定的 color 和 variant 组合应用样式。
import type { ModuleOptions } from '../module'
export default (options: Required<ModuleOptions>) => ({
slots: {
base: ['rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75', options.theme.transitions && 'transition-colors']
},
variants: {
color: {
...Object.fromEntries((options.theme.colors || []).map((color: string) => [color, ''])),
neutral: ''
},
variant: {
solid: '',
outline: '',
soft: '',
subtle: '',
ghost: '',
link: ''
}
},
compoundVariants: [
...(options.theme.colors || []).map((color: string) => ({
color,
variant: 'outline',
class: `ring ring-inset ring-${color}/50 text-${color} hover:bg-${color}/10 active:bg-${color}/10 disabled:bg-transparent aria-disabled:bg-transparent dark:disabled:bg-transparent dark:aria-disabled:bg-transparent focus:outline-none focus-visible:ring-2 focus-visible:ring-${color}`
})),
{
color: 'neutral',
variant: 'outline',
class: 'ring ring-inset ring-accented text-default bg-default hover:bg-elevated active:bg-elevated disabled:bg-default aria-disabled:bg-default focus:outline-none focus-visible:ring-2 focus-visible:ring-inverted'
}
],
defaultVariants: {
color: 'primary',
variant: 'solid'
}
})
自定义主题
你有多种方式来自定义 Nuxt UI 组件的外观,既可以针对所有组件进行全局设置,也可以按组件进行逐一设置。
tailwind-merge 来合并类名,因此你不必担心冲突。- 查看每个独立组件文档中的
Theme部分。 - 直接在 GitHub 仓库的
src/theme目录中浏览源代码。
全局配置
你可以在 app.config.ts 中使用与主题对象完全相同的结构,全局覆盖组件的主题。
你可以在 vite.config.ts 中使用与主题对象完全相同的结构,全局覆盖组件的主题。
你可以自定义slots, variants, compoundVariants和defaultVariants以更改组件的默认主题。
export default defineAppConfig({
ui: {
button: {
slots: {
base: 'font-bold'
},
variants: {
size: {
md: {
leadingIcon: 'size-4'
}
}
},
compoundVariants: [{
color: 'neutral',
variant: 'outline',
class: 'ring-default hover:bg-accented'
}],
defaultVariants: {
color: 'neutral',
variant: 'outline'
}
}
}
})
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'
},
variants: {
size: {
md: {
leadingIcon: 'size-4'
}
}
},
compoundVariants: [{
color: 'neutral',
variant: 'outline',
class: 'ring-default hover:bg-accented'
}],
defaultVariants: {
color: 'neutral',
variant: 'outline'
}
}
}
})
]
})
font-bold 覆盖了所有按钮上的 font-medium,size-4 覆盖了前置图标在 size="md" 时的 size-5 类,而 ring-default hover:bg-accented 覆盖了 color="neutral" 和 variant="outline" 时的 ring-accented hover:bg-elevated。按钮现在默认使用 color="neutral" 和 variant="outline"。ui 属性
你还可以使用 ui 属性覆盖组件的 slots。此属性的优先级高于全局配置和已解析的 variants。
<template>
<UButton
trailing-icon="i-lucide-chevron-right"
size="md"
color="neutral"
variant="outline"
:ui="{
trailingIcon: 'rotate-90 size-3'
}"
>
Button
</UButton>
</template>
trailingIcon 插槽被 size-3 覆盖,尽管 md 大小变体会为其应用 size-5 类。class 属性
class 属性允许你覆盖 root 或 base 插槽的样式。此属性的优先级高于全局配置和已解析的 variants。
<template>
<UButton class="font-bold rounded-full">Button</UButton>
</template>
font-bold 类将覆盖此按钮上的默认 font-medium 类。