Skip to content

Vue 3

@theme-kit/vue

Composition APIProvider

Composables-first theming for Vue 3 with a provider component and scoped theming.

Installation

Install the package for your framework alongside @theme-kit/core.

bash
pnpm add @theme-kit/vue

Quick Start

Start from scratch — install the package, then wrap your app in the provider at the entry point shown below.

App.vue
vue
1<script setup>
2import { ThemeProvider } from "@theme-kit/vue";
3import { themes } from "./themes";
4</script>
5
6<template>
7  <ThemeProvider :themes="themes" default-theme="mint-light">
8    <YourView />
9  </ThemeProvider>
10</template>
Every integration re-exports the full @theme-kit/core surface, so history, batching, snapshots, packs and lifecycle work the same way across frameworks.

Implementation

Read and update theme state from any component using the framework-native primitives below.

ThemeSwitcher.vue
vue
1<script setup>
2import { useTheme } from "@theme-kit/vue";
3const { theme, mode, toggleTheme } = useTheme();
4</script>
5
6<template>
7  <button @click="toggleTheme">{{ theme.name }} · {{ mode }}</button>
8</template>

What's Available

@theme-kit/vue ships 15 exports in 5 categories. Everything below is also documented in the full API reference. Click any export to reveal what it does and how to use it.

Setup

Composables

Library adapters

Transition

Components

Use Cases

The important features in practice — copy any of these straight into your app.

Toggle light / dark

useTheme exposes refs and setters — reactive in templates and scripts.

Toggle light / dark
vue
1<script setup>
2import { useTheme } from "@theme-kit/vue";
3const { theme, mode, family, setMode, setFamily, toggleTheme } = useTheme();
4</script>
5
6<template>
7  <button @click="toggleTheme">{{ theme.name }} · {{ mode }}</button>
8  <button @click="setMode('dark')">Dark</button>
9  <select v-model="family" @change="setFamily(family)">
10    <option value="neutral">Neutral</option>
11    <option value="mint">Mint</option>
12  </select>
13</template>

Undo / redo theme changes

History state is reactive; use it to build undo/redo controls.

Undo / redo theme changes
vue
1<script setup>
2import { useThemeHistory, useThemeRuntime } from "@theme-kit/vue";
3const { undo, redo, canUndo, canRedo } = useThemeHistory();
4const runtime = useThemeRuntime();
5</script>
6
7<template>
8  <button :disabled="!canUndo" @click="undo">Undo</button>
9  <button :disabled="!canRedo" @click="redo">Redo</button>
10  <button @click="runtime.update({ colors: { primary: '#6366f1' } })">
11    Make primary indigo
12  </button>
13</template>

Scope a subtree

ThemeScope applies a theme to a slot with scoped CSS variables.

Scope a subtree
vue
1<script setup>
2import { ThemeScope, type ThemeTransitionOptions } from "@theme-kit/vue";
3
4const transition: ThemeTransitionOptions = { duration: 300, easing: "ease" };
5</script>
6
7<template>
8  <Sidebar />
9  <ThemeScope theme="forest" :transition="transition">
10    <DataViz />
11  </ThemeScope>
12</template>

Lifecycle events

Subscribe to typed lifecycle events and react to changes.

Lifecycle events
vue
1<script setup>
2import { onMounted } from "vue";
3import { useThemeLifecycle, useThemePacks } from "@theme-kit/vue";
4
5const { on } = useThemeLifecycle();
6const usePack = useThemePacks();
7
8onMounted(() => {
9  on("beforeThemeChange", (e) => console.log("changed to", e.next.name));
10});
11</script>
12
13<template>
14  <button @click="usePack({ name: 'a11y', themes: highContrast })">
15    Apply High Contrast pack
16  </button>
17</template>

Smooth theme transitions

Enable CSS transitions on theme changes for a polished user experience.

Smooth theme transitions
vue
1<script setup>
2import { ThemeProvider } from "@theme-kit/vue";
3</script>
4
5<template>
6  <ThemeProvider
7    :themes="themes"
8    :transition="{ enabled: true, duration: 300, easing: 'ease-in-out' }"
9  >
10    <YourView />
11  </ThemeProvider>
12</template>

More Examples

Scoped theming, history controls, and framework-specific patterns.

history + scope
vue
1<script setup>
2import { useThemeHistory } from "@theme-kit/vue";
3const { undo, redo, canUndo, canRedo } = useThemeHistory();
4</script>
5
6<template>
7  <button @click="undo" :disabled="!canUndo">Undo</button>
8  <button @click="redo" :disabled="!canRedo">Redo</button>
9
10  <ThemeScope theme="forest">
11    <p>This subtree is always themed "forest".</p>
12  </ThemeScope>
13</template>

API Reference

Setup

ExportDescription
ThemeProviderProvider component accepting every runtime option; auto-registered via `app.use` (`.install`).
provideThemeRuntime() / useThemeRuntime()Explicit provide/inject access to the runtime.

Composables

ExportDescription
useTheme()Reactive refs for `theme`, `mode`, `family` plus `setMode`, `setFamily`, `toggleTheme`.
useThemeHistory()Undo / redo / jump through theme history.
useThemeBatch()Atomic, coalesced updates via `runtime.batch()`.
useThemeSnapshot() / useThemeRestore()Serialize and restore the full runtime state.
useThemeLifecycle()Subscribe to typed lifecycle events.
useThemePacks()Install theme packs at runtime.
useThemeSchedule()Reactive schedule state (a `Ref` with `enabled`, `status`, `sunrise`, `sunset`, `nextTransition`) plus `enable()`/`disable()`/`set()`. Configure via the `scheduled` prop on ThemeProvider.

Library adapters

ExportDescription
useShadcnTheme() / useBootstrapTheme()Framework composables install the React-free CSS-variable adapter factories and dispose the returned adapter handle with the component lifecycle.
useDaisyTheme() / useOpenPropsTheme()Same adapter contract for DaisyUI and Open Props; the framework package supplies lifecycle wiring while the adapter factory stays framework-neutral.
adapter factory subpathsUse `@theme-kit/shadcn/factory`, `@theme-kit/bootstrap/factory`, `@theme-kit/daisyui/factory`, or `@theme-kit/open-props/factory` when you need the adapter without React.

Transition

ExportDescription
transition propPass `transition` to ThemeProvider to enable CSS transitions on theme changes.
runtime.store.set(theme, { suppressTransition: true })Runtime toggle — no mutation hook exists. The transition prop is fixed at runtime creation; for a one-off instant switch, get the runtime (useThemeRuntime() / getThemeRuntime()) then runtime.store.set(theme, { suppressTransition: true }) applies immediately without animating. For full control, compose createThemeDiff + createTransitionPlan + runThemeAnimation from @theme-kit/core.

Components

ExportDescription
ThemeScopeScoped theming component for subtrees.
Vue 3 — Theme Kit