Theme
Utilisation
Le composant Theme remplace les classes par défaut **slot ** et props de tous les composants enfants sans modifier chacun individuellement. Il utilise le mécanisme provide/inject de Vue sous le capot, de sorte que les remplacements s'appliquent à toute profondeur.
app.config.ts.vite.config.ts.Slot classes
Utilisez la prop ui pour remplacer les classes d'emplacement des composants descendants. Les clés sont des noms de composants (camelCase) et les valeurs sont leurs remplacements de classe d'emplacement.
<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>
Prop par défaut: badge{label="4.8+" class="align-text-top"}
Utilisez la prop props pour remplacer la valeur par défaut de n'importe quelle prop sur les composants descendants.
<template>
<UTheme
:props="{
button: { color: 'neutral', variant: 'subtle', size: 'lg' },
tooltip: { delayDuration: 0, arrow: true }
}"
>
<div class="flex items-center gap-2">
<UTooltip text="Inherits delayDuration from theme">
<UButton label="Hover me" />
</UTooltip>
<UButton label="With icon" icon="i-lucide-rocket" />
<UButton label="Square" icon="i-lucide-star" square />
</div>
</UTheme>
</template>
<UButton color="primary" />) l'emportent toujours sur <UTheme :props>. Les valeurs par défaut du thème ne s'appliquent que lorsque la prop n'a pas été passée explicitement.exemples
Composants multiples
Utilisez différentes touches dans ui ou props pour thématiser plusieurs types de composants à la fois.
<template>
<UTheme
:props="{
button: { color: 'neutral', variant: 'outline', size: 'lg' },
input: { size: 'lg' },
select: { size: 'lg' }
}"
:ui="{
button: { base: 'rounded-full' },
input: { base: 'rounded-full' },
select: { base: 'rounded-full' }
}"
>
<div class="flex items-center gap-2">
<UButton label="Button" />
<UInput placeholder="Search..." />
<USelect placeholder="Select" :items="['Item 1', 'Item 2', 'Item 3']" />
</div>
</UTheme>
</template>
Thèmes imbriqués
Imbriquez plusieurs composants de thème pour composer des remplacements. Le thème le plus interne a la priorité, tandis que les clés non remplacées sont héritées du thème externe.
<template>
<UTheme
:ui="{
button: {
base: 'rounded-full'
}
}"
>
<div class="flex flex-col items-start gap-4 border border-muted p-4 rounded-lg">
<div class="flex items-center gap-2">
<UButton label="Outer theme" />
<UButton label="Outer theme" color="neutral" variant="outline" />
</div>
<UTheme
:ui="{
button: {
base: 'font-black uppercase'
}
}"
>
<div class="border border-muted p-4 rounded-lg">
<div class="flex items-center gap-2">
<UButton label="Inner theme" />
<UButton label="Inner theme" color="neutral" variant="outline" />
</div>
</div>
</UTheme>
</div>
</UTheme>
</template>
Priorité explicite
Le paramétrage explicite d'un prop (y compris ui) sur un composant individuel a toujours priorité sur le composant Thème.
<template>
<UTheme
:ui="{
button: {
base: 'rounded-full'
}
}"
>
<div class="flex items-center gap-2">
<UButton label="Themed" />
<UButton label="Overridden" :ui="{ base: 'rounded-none' }" />
</div>
</UTheme>
</template>
Propagation profonde
Les remplacements sont disponibles pour tous les composants descendants, quelle que soit leur profondeur d'imbriquage.
<script setup lang="ts">
import MyButton from './MyButton.vue'
</script>
<template>
<UTheme
:ui="{
button: {
base: 'rounded-full'
}
}"
>
<UCard :ui="{ body: 'flex items-center gap-2 sm:flex-row flex-col' }">
<UButton label="Direct child" />
<MyButton />
</UCard>
</UTheme>
</template>
MyButton est un composant personnalisé qui rend un UButton en interne. Les remplacements de thème s'appliquent toujours car ils se propagent dans toute l'arborescence des composants.Form composants
Utilisez le composant Thème pour appliquer un style cohérent à un groupe de composants de formulaire.
<script setup lang="ts">
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = z.object({
name: z.string().min(2, 'Too short'),
email: z.email('Invalid email'),
bio: z.string().optional()
})
type Schema = z.output<typeof schema>
const state = reactive<Partial<Schema>>({
name: 'John Doe',
email: 'john@example.com',
bio: undefined
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Saved', description: 'Your profile has been updated.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UTheme
:props="{
input: { size: 'lg' },
textarea: { size: 'lg' }
}"
:ui="{
formField: {
root: 'flex max-sm:flex-col justify-between gap-4',
wrapper: 'w-full sm:max-w-xs'
}
}"
>
<UForm :schema="schema" :state="state" class="space-y-4 w-full" @submit="onSubmit">
<UFormField label="Name" name="name" description="Your public display name.">
<UInput v-model="state.name" />
</UFormField>
<UFormField label="Email" name="email" description="Used for notifications.">
<UInput v-model="state.email" type="email" />
</UFormField>
<UFormField label="Bio" name="bio" description="A short description about yourself.">
<UTextarea v-model="state.bio" placeholder="Tell us about yourself" />
</UFormField>
<div class="flex justify-end">
<UButton type="submit">
Save changes
</UButton>
</div>
</UForm>
</UTheme>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import * as z from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
const schema = z.object({
name: z.string().min(2, 'Too short'),
email: z.email('Invalid email'),
bio: z.string().optional()
})
type Schema = z.output<typeof schema>
const state = reactive<Partial<Schema>>({
name: 'John Doe',
email: 'john@example.com',
bio: undefined
})
const toast = useToast()
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({ title: 'Saved', description: 'Your profile has been updated.', color: 'success' })
console.log(event.data)
}
</script>
<template>
<UTheme
:props="{
input: { size: 'lg' },
textarea: { size: 'lg' }
}"
:ui="{
formField: {
root: 'flex max-sm:flex-col justify-between gap-4',
wrapper: 'w-full sm:max-w-xs'
}
}"
>
<UForm :schema="schema" :state="state" class="space-y-4 w-full" @submit="onSubmit">
<UFormField label="Name" name="name" description="Your public display name.">
<UInput v-model="state.name" />
</UFormField>
<UFormField label="Email" name="email" description="Used for notifications.">
<UInput v-model="state.email" type="email" />
</UFormField>
<UFormField label="Bio" name="bio" description="A short description about yourself.">
<UTextarea v-model="state.bio" placeholder="Tell us about yourself" />
</UFormField>
<div class="flex justify-end">
<UButton type="submit">
Save changes
</UButton>
</div>
</UForm>
</UTheme>
</template>
<UFormField>, <UFieldGroup> et <UAvatarGroup> conservent la priorité sur <UTheme :props> pour size, color et highlight. Les erreurs de validation forcent également la couleur error sur n'importe quelle valeur de thème.Composants ### Prose
Utilisez l'espace de noms prose pour thématiser les composants de typographie. Les touches sont imbriquées sous prose (par exemple, prose.p, prose.code).
Getting started
This is a paragraph with a tighter typographic scale applied through the Theme component.
- First item
- Second item
- Third item
The spacing and font sizes are smaller than the defaults, making it ideal for compact content areas.
<script setup lang="ts">
import { Markdown } from '@comark/vue'
const ui = {
prose: {
p: { base: 'my-2.5 text-sm/6' },
li: { base: 'my-0.5 text-sm/6' },
ul: { base: 'my-2.5' },
ol: { base: 'my-2.5' },
h1: { base: 'text-xl mb-4' },
h2: { base: 'text-lg mt-6 mb-3' },
h3: { base: 'text-base mt-4 mb-2' },
h4: { base: 'text-sm mt-3 mb-1.5' },
code: { base: 'text-xs' },
pre: { root: 'my-2.5', base: 'text-xs/5' },
table: { root: 'my-2.5' },
hr: { base: 'my-5' }
}
}
const value = `## Getting started
This is a paragraph with a **tighter typographic scale** applied through the \`Theme\` component.
- First item
- Second item
- Third item
> The spacing and font sizes are smaller than the defaults, making it ideal for compact content areas.`
</script>
<template>
<UTheme :ui="ui">
<Markdown :value="value" class="*:first:mt-0 *:last:mb-0" />
</UTheme>
</template>
api
Props
| Prop | Default | Type |
|---|---|---|
props | ThemeDefaultsPer-component prop defaults that flow through | |
ui | ThemeUIPer-component slot class overrides (flat shorthand for |
Slots
| Slot | Type |
|---|---|
default | {} |