Skip to content

useTheme()

The core composable for managing themes in Vue 3 components.

Signature

ts
function useTheme(options: ThemeOptions): UseThemeReturn

Options

PropertyTypeDefaultDescription
themesThemeDefinition[]requiredArray of theme definitions
defaultThemestringFirst themeName of initial theme
strategy'attribute' | 'class' | 'both''attribute'How theme is applied to DOM
attributestring'data-theme'Attribute name for attribute strategy
classPrefixstring'theme-'Class prefix for class strategy
target'html' | 'body' | string'html'DOM element to apply theme to
storage'localStorage' | 'sessionStorage' | 'none''localStorage'Persistence mode
storageKeystring'vmt-theme'Storage key for persistence
injectCssVarsbooleantrueAuto-inject CSS custom properties
cssVarPrefixstring'--vmt-'Prefix for CSS variables
namespacestringundefinedNamespace for isolated contexts
respectSystemPreferencebooleanfalseAuto-select based on OS preference
onChange(theme: ThemeDefinition) => voidundefinedCallback after each change
onThemeChange(newTheme: string, oldTheme: string) => voidundefinedCallback with old + new names

Return Value

useTheme() returns a reactive object. Properties auto-unwrap in templates (no .value):

PropertyTypeDescription
currentstringActive theme name (reactive)
themeThemeDefinitionFull definition of active theme (reactive)
isDarkbooleantrue if background luminance < 0.5 (reactive)
themesThemeDefinition[]All available themes
resolvedColorsRecord<string, { r, g, b }>Parsed RGB values of active theme
setTheme(name)(name: string) => voidSet theme by name
nextTheme()() => voidCycle to next theme
prevTheme()() => voidCycle to previous theme
toggleTheme()() => voidToggle between first two themes

Example

vue
<script setup lang="ts">
import { useTheme, PRESET_THEMES } from 'vue-multiple-themes'
import { watch } from 'vue'

const ts = useTheme({
  themes: PRESET_THEMES,
  defaultTheme: 'light',
  strategy: 'both',
  respectSystemPreference: true,
  onThemeChange: (next, prev) => {
    console.log(`Theme: ${prev} → ${next}`)
  },
})

// Watch for changes
watch(() => ts.current, (name) => {
  document.title = `App — ${name} theme`
})
</script>

<template>
  <div>
    <span>{{ ts.current }} (dark: {{ ts.isDark }})</span>
    <button @click="ts.toggleTheme">Toggle</button>
    <button @click="ts.nextTheme">Next</button>
  </div>
</template>

Singleton Behavior

Multiple useTheme() calls with the same storageKey (and namespace) share a singleton reactive state. This is intentional — the same theme state is shared across your entire app.

ts
// Component A
const { setTheme } = useTheme({ themes, storageKey: 'my-theme' })

// Component B — same reactive state as A
const { current } = useTheme({ themes, storageKey: 'my-theme' })

setTheme('dark') // Both components react to this change

Released under the MIT License.