Composants personnalisés
Tailwind Variants
Les composants de l'interface utilisateur Nuxt sont stylisés à l'aide de l'API Tailwind Variants, qui fournit un moyen puissant de créer des variantes et de gérer les styles de composants.
Slots
Les composants peuvent avoir plusieurs slots, chacun représentant un élément ou une section HTML distincte au sein du composant.
Prenons l'exemple du composant Card qui possède plusieurs emplacements:
export default {
slots: {
root: 'rounded-lg overflow-hidden',
header: 'p-4 sm:px-6',
title: 'text-highlighted font-semibold',
description: 'mt-1 text-muted text-sm',
body: 'p-4 sm:p-6',
footer: 'p-4 sm:px-6'
}
}
<template>
<Primitive :as="props.as" data-slot="root" :class="ui.root({ class: [props.ui?.root, props.class] })">
<div data-slot="header" :class="ui.header({ class: props.ui?.header })">
<slot name="header" />
</div>
<div data-slot="body" :class="ui.body({ class: props.ui?.body })">
<slot />
</div>
<div data-slot="footer" :class="ui.footer({ class: props.ui?.footer })">
<slot name="footer" />
</div>
</Primitive>
</template>
v-if sur chaque emplacement et le thème définit les styles variant sur le dessus des emplacements.En este caso, el tema solo define la ranura base como el componente Container por ejemplo:
export default {
base: 'w-full max-w-(--ui-container) mx-auto px-4 sm:px-6 lg:px-8'
}
<template>
<Primitive :as="props.as" :class="ui({ class: [props.ui?.base, props.class] })">
<slot />
</Primitive>
</template>
base au lieu d'une clé par emplacement. Link et [Iconxph072/docs/components/icon) sont les exceptions: ils n'ont pas de prop ui, donc utilisez le [ph062x propxph077) pour remplacer leurs styles.Variants
Les composants prennent en charge variants, qui ajustent dynamiquement les styles de différents slots en fonction des accessoires des composants.
Par exemple, le composant Avatar utilise une variante size pour contrôler son apparence:
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'
}
}
De cette façon, le prop size appliquera les styles correspondants au slot root:
<template>
<UAvatar src="https://github.com/nuxt.png" size="lg" />
</template>Default Variants par défaut
La propriété defaultVariants définit la valeur par défaut pour chaque variante lorsqu 'aucun prop n'est passé.
Par exemple, le composant Avatar a sa taille par défaut définie sur 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'
}
}
theme.defaultVariants dans votre nuxt.config.ts pour remplacer les size et color par défaut de chaque composant qui utilise md et primary.theme.defaultVariants dans votre vite.config.ts pour remplacer les size et color par défaut de chaque composant qui utilise md et primary.Variantes composées
Certains composants utilisent la propriété compoundVariants pour appliquer des classes lorsque plusieurs conditions de variantes sont remplies en même temps.
Par exemple, le composant Button utilise la propriété compoundVariants pour appliquer des classes pour une combinaison spécifique de color et 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 outline-${color}/25 focus-visible:outline-3 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 outline-inverted/25 focus-visible:outline-3 focus-visible:ring-inverted'
}
],
defaultVariants: {
color: 'primary',
variant: 'solid'
}
})
Personnaliser thème
Vous avez plusieurs façons de personnaliser l'apparence des composants de l'interface utilisateur Nuxt, vous pouvez le faire pour tous les composants à la fois ou par composant.
tailwind-merge sous le capot pour fusionner les classes afin que vous n'ayez pas à vous soucier des classes conflictuelles.Theme dans la documentation de chaque composant.- Parcourez le code source directement dans le dépôt GitHub à
src/theme
Configuration globale
Vous pouvez remplacer le thème des composants globalement à l'intérieur de votre app.config.ts en utilisant exactement la même structure que l'objet thème.
You can override the theme of components globally inside your vite.config.ts by using the exact same structure as the theme object.
Vous pouvez personnaliser les xslots, , compoundVariants et defaultVariants d'un composant pour modifier le thème par défaut d'un composant:
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 remplace font-medium sur tous les boutons, size-4 remplace la classe size-5 sur l'icône principale quand size="md" et ring-default hover:bg-accented remplace ring-accented hover:bg-elevated quand color="neutral" et variant="outline".Par défaut, ces classes sont fusionnées sur les valeurs par défaut du composant. Vous pouvez également définir un emplacement pour une fonction pour les remplacer à la place. Il reçoit les classes par défaut de l'emplacement comme argument, de sorte que vous pouvez réutiliser une partie d'entre elles. Les classes de variants et compoundVariants s'appliquent toujours en haut, exactement comme lorsque vous passez une chaîne.
export default defineAppConfig({
ui: {
button: {
slots: {
label: () => 'text-base font-bold'
}
}
}
})
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: {
label: () => 'text-base font-bold'
}
}
}
})
]
})
app.config.ts de chaque layer avec defuFn, qui appelle votre fonction avec la valeur que la clé a déjà plus bas et ne conserve que le résultat. Nuxt UI lit ensuite une chaîne de caractères simple, de sorte que ses classes sont fusionnées sur les valeurs par défaut au lieu de les remplacer.theme.unstyled dans votre nuxt.config.ts.theme.unstyled dans votre vite.config.ts.Composant ### Theme
Le composant Theme remplace les slots et les valeurs par défaut de prop pour tous ses descendants, sans affecter le reste de l'application. mais les accessoires ui et class l'emportent toujours. Les machines à sous acceptent la même forme de fonction pour remplacer leurs classes au lieu de fusionner. Elle est résolue au même point que le ui prop, il se comporte donc de la même manière.
<template>
<UTheme
:ui="{
button: {
base: 'rounded-full'
}
}"
>
<div class="flex items-center gap-2">
<UButton label="Button" color="neutral" />
<UButton label="Button" color="neutral" variant="outline" />
<UButton label="Button" color="neutral" variant="subtle" />
</div>
</UTheme>
</template>
ui prop
Vous pouvez également remplacer slots d'un composant en utilisant la prop. ui Ceci a la priorité sur la configuration globale et variants résolu.
<template>
<UButton
trailing-icon="i-lucide-chevron-right"
size="md"
color="neutral"
variant="outline"
:ui="{
trailingIcon: 'rotate-90 size-3'
}"
>
Button
</UButton>
</template>trailingIcon est écrasé par size-3, même si la variante de taille md lui appliquerait une classe size-5.Une valeur de slot peut aussi être une fonction pour remplacer ses classes au lieu de les fusionner:
<template>
<UButton :ui="{ label: () => 'text-base font-bold' }" label="Button" />
</template>
ui est résolue après la prop variants, donc contrairement à la configuration globale, une fonction remplace ici les classes resolved de l'emplacement. Son argument contient ce que les classes variants et compoundVariants ont correspondu. Une prop class sur le même emplacement est toujours fusionnée au-dessus des classes retournées.xclass prop
Utilisez la prop class pour remplacer les classes de l'emplacement root ou base. Ceci a la priorité sur la configuration globale et le variants résolu.
<template>
<UButton class="font-bold rounded-full">Button</UButton>
</template>font-bold remplacera la classe font-medium par défaut sur ce bouton.