Theme
Scopes a theme to a component subtree for independently themed sections of your app.
Usage
Wrap any section of your template in <Theme> to override the active theme for that subtree. Children calling useTheme() will see the scoped theme as the current selection. When no theme prop is provided, it inherits the parent theme — useful for wrapping content that needs the data-theme attribute without changing the active theme.
<script setup lang="ts">
import { Theme } from '@vuetify/v0'
</script>
<template>
<Theme theme="dark">
<!-- Everything here sees "dark" as the active theme -->
<slot />
</Theme>
</template>Anatomy
<script setup lang="ts">
import { Theme } from '@vuetify/v0'
</script>
<template>
<Theme />
</template>Examples
Root context (light)
Recipes
Polymorphic Rendering
Theme extends Atom, so it accepts the as prop to render as any HTML element:
<template>
<Theme theme="dark" as="section">
<!-- renders as <section data-theme="dark"> -->
</Theme>
</template>Renderless Mode
Set renderless to skip the wrapper element. The slot exposes attrs (including data-theme) for you to bind to your own element:
<template>
<Theme theme="dark" renderless v-slot="{ attrs }">
<section v-bind="attrs">
No extra wrapper div
</section>
</Theme>
</template>Isolated Context
By default, <Theme> provides its context under the 'v0:theme' key — the same key used by useTheme(). If you’re building a component that needs its own theme scope that doesn’t interfere with the app’s global theme, pass a custom namespace:
<template>
<!-- Isolated: useTheme() in descendants won't affect the global theme -->
<Theme theme="dark" namespace="my-widget:theme">
<slot />
</Theme>
</template> The namespace prop is only needed when building reusable components that must be theme-isolated. Most apps don’t need it.
Slot Props
The default slot exposes theme (the active ID), isDark (boolean), and attrs for conditional rendering:
<template>
<Theme v-slot="{ theme, isDark }" theme="dark">
<span>{{ theme }} — dark: {{ isDark }}</span>
</Theme>
</template>Accessibility
Theme is a headless context provider. It scopes theme state to a subtree and writes a data-theme attribute on its wrapper element for CSS variable targeting; it adds no ARIA attributes, roles, or keyboard behavior, and it introduces no interactive elements of its own.
Theme selection is a visual concern, not a semantic one — a scoped theme changes token values, not the accessibility tree. Ensure the color choices in every theme you expose meet WCAG contrast requirements↗︎; the component does not enforce contrast for you.
FAQ
No. It scopes the theme to its subtree — descendant useTheme() calls resolve to the override while the rest of the app is unaffected.
Omit the theme prop. Theme then inherits the parent theme while still emitting the data-theme attribute on its wrapper, which your CSS variable declarations can target.
Only when building a reusable component that must stay theme-isolated from the app’s global theme. By default Theme provides under 'v0:theme' (the key useTheme() reads); a custom namespace keeps descendants from affecting the global theme. Most apps don’t need it.
Yes. Theme extends Atom, so the as prop renders it as any element — <Theme theme="dark" as="section"> outputs <section data-theme="dark">.
Set renderless and bind the attrs slot prop (which includes data-theme) to your own element.