Theme
使用法
Themeコンポーネントは、すべての子コンポーネントのデフォルトのslot classesとpropsを個別に変更することなくオーバーライドします。内部ではVueのprovide/injectメカニズムを使用しているため、オーバーライドはどんな深さでも適用されます。
app.config.tsファイルを使用することをお勧めします。vite.config.tsファイルを使用することをお勧めします。Slotクラス
uiプロパティを使用して子孫コンポーネントのスロットクラスをオーバーライドします。キーはコンポーネント名camelCaseで、値はそれらのスロットクラスのオーバーライドです。
<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デフォルトbadge{label="4.8+" class="align-text-top"}
propsプロパティを使用して、子孫コンポーネントのプロパティのデフォルト値をオーバーライドします。各キーは、そのコンポーネントのプロパティの一部にマップされます。
<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" />は常に<UTheme :props>に勝ちます。テーマのデフォルトはプロップが明示的に渡されなかった場合にのみ適用されます。例
複数コンポーネント
uiまたはpropsの異なるキーを使用して、複数のコンポーネントタイプを一度にテーマにします。
<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>
ネストされたテーマ
オーバーライドを作成するために複数のテーマコンポーネントをネストします。最も内側のテーマが優先され、オーバーライドされていないキーは外側のテーマから継承されます。
<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>
明示的優先度
個々のコンポーネントに明示的にプロパティ(uiを含む)を設定すると、常にテーマコンポーネントよりも優先されます。
<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>
Deep伝播
オーバーライドは、どれだけ深くネストされているかに関係なく、すべての子孫コンポーネントが使用できます。
<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はUButtonを内部的にレンダリングするカスタムコンポーネントです。テーマオーバーライドはコンポーネントツリー全体を伝播するため、引き続き適用されます。Formコンポーネント
テーマコンポーネントを使用して、フォームコンポーネントのグループに一貫したスタイルを適用します。
<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>
size、color、highlightでは、<UFormField>、<UFieldGroup>、<UAvatarGroup>が<UTheme :props>よりも優先されます。バリデーションエラーは、errorの色をテーマ値に強制します。散文コンポーネント
prose名前空間を使用して、タイポグラフィコンポーネントをテーマにします。キーはproseの下にネストされます(例: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 |
スロット
| Slot | Type |
|---|---|
default | {} |