Componentes customizados
Variantes de ## Tailwind
Los componentes de la interfaz de usuario de Nuxt se diseñan utilizando la API Tailwind Variants, que proporciona una forma poderosa de crear variantes y administrar estilos de componentes.
Slots
Los componentes pueden tener múltiples slots, cada uno representando un elemento HTML distinto o sección dentro del componente.
Tomemos como ejemplo el componente Card que tiene múltiples ranuras:
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 en cada ranura y el tema define los estilos variant en la parte superior de las ranuras.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 en lugar de una clave por ranura. Link y [Iconxph072/docs/components/icon) son las excepciones: no tienen prop ui, así que use el [class propxph076) para anular sus estilos.Variaciones
Los componentes soportan variants, que ajusta dinámicamente los estilos de diferentes slots basados en los accesorios de los componentes.
Por ejemplo, el componente Avatar utiliza una variante size para controlar su apariencia:
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 esta manera, el accesorio size aplicará los estilos correspondientes a la ranura root:
<template>
<UAvatar src="https://github.com/nuxt.png" size="lg" />
</template>Variantes por defecto
La propiedad defaultVariants establece el valor por defecto para cada variante cuando no se pasa ningún prop.
Por ejemplo, el componente Avatar tiene su tamaño predeterminado establecido en 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 en su nuxt.config.ts para anular los valores size y color predeterminados de cada componente que utilice md y primary.theme.defaultVariants en su vite.config.ts para anular los valores size y color predeterminados de cada componente que utilice md y primary.Variantes de compuesto
Algunos componentes usan la propiedad compoundVariants para aplicar clases cuando se cumplen varias condiciones de variante al mismo tiempo.
Por ejemplo, el componente Button utiliza la propiedad compoundVariants para aplicar clases para una combinación específica de color y 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'
}
})
Personalizar el tema
Hay varias formas de personalizar la apariencia de los componentes de la interfaz de usuario de Nuxt, puede hacerlo para todos los componentes a la vez o por componente.
tailwind-merge bajo el capó para combinar clases para que no tenga que preocuparse por clases en conflicto.- Compruebe la sección
Themeen la documentación de cada componente. Examine el código fuente directamente en el repositorio de GitHub ensrc/theme.
Configuración global
Puede anular el tema de los componentes de forma global dentro de su app.config.ts utilizando la misma estructura que el objeto de tema.
Puede anular el tema de los componentes de forma global dentro de su vite.config.ts utilizando la misma estructura que el objeto de tema.
Puede personalizar el xslots, variants, compoundVariants y xph2444xdefaultVariants](#default-variants) de un componente para cambiar el tema predeterminado de un componente:
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 reemplaza a font-medium en todos los botones, size-4 reemplaza a la clase size-5 en el icono principal cuando size="md" y ring-default hover:bg-accented reemplaza a ring-accented hover:bg-elevated cuando color="neutral" y variant="outline".De forma predeterminada, estas clases se combinan con los valores predeterminados del componente.También puede establecer una ranura para una función para reemplazarlos en su lugar.Recibe las clases predeterminadas de la ranura como argumento, por lo que puede reutilizar parte de ellas.Las clases de variants y compoundVariants aún se aplican en la parte superior, exactamente como cuando pasa una cadena.
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 cada layer con defuFn, que llama a tu función con cualquier valor que la clave ya tenga más abajo y mantiene solo el resultado.theme.unstyled en su nuxt.config.ts.theme.unstyled en su vite.config.ts.Componente ### Theme
El componente Theme anula los slots y los valores predeterminados de prop para todos sus descendientes, sin afectar al resto de la aplicación. pero los accesorios ui y class aún lo ganan. Las tragamonedas aceptan la misma forma de función para reemplazar sus clases en lugar de fusionarse. Se resuelve en el mismo punto que el ui prop, por lo que se comporta de la misma manera.
<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>
xui Prop.
También puede anular el slots de un componente usando el prop. ui Esto tiene prioridad sobre la configuración global y el variants resuelto.
<template>
<UButton
trailing-icon="i-lucide-chevron-right"
size="md"
color="neutral"
variant="outline"
:ui="{
trailingIcon: 'rotate-90 size-3'
}"
>
Button
</UButton>
</template>trailingIcon se sobrescribe con size-3 a pesar de que la variante de tamaño md le aplicaría una clase size-5.Un valor slot también puede ser una función para reemplazar sus clases en lugar de fusionarlas:
<template>
<UButton :ui="{ label: () => 'text-base font-bold' }" label="Button" />
</template>
ui se resuelve después del variants, por lo que a diferencia de la configuración global, una función aquí reemplaza las clases resolved de la ranura. Su argumento contiene lo que coinciden los variants y compoundVariants. Un prop class en la misma ranura todavía se combina en la parte superior de las clases devueltas.xclass Prop.
Utilice el prop class para anular las clases de la ranura root o base. Esto tiene prioridad sobre la configuración global y la resolución de variants.
<template>
<UButton class="font-bold rounded-full">Button</UButton>
</template>font-bold anulará la clase font-medium predeterminada en este botón.