Theme Switcher

VdThemeSwitcher is a lightweight control for toggling between light, dark, and system color modes. It drives the shared useThemePreference() singleton, so it stays in sync with VdThemeCustomizer and persists to localStorage. Render it as an icon menu (default) or a single cycling button.

Live Demo

These are real <VdThemeSwitcher> instances — picking a mode re-themes this whole page:

Icon Menu (default)

Menu, align="end"

Cycle Button

Current theme: system

Coordination with VdThemeCustomizer: both components read and write the same useThemePreference() singleton, so a mode change in either is immediately visible in the other. If the primary color is still the auto default, switching modes re-derives it for the new scheme (see setThemeDefaults below).
Icon Menu (Recommended)

The default variant. The toggle opens an icon-only picker; the theme only changes once the user chooses an option — ideal for a navbar. Use align="end" to hang the menu off the toggle's trailing edge:

<script setup lang="ts">
import { VdThemeSwitcher } from "@vanduo-oss/vd3";

const onChange = (mode: "system" | "light" | "dark") => {
  console.log("theme changed:", mode);
};
</script>

<template>
  <!-- Icon menu (default) — recommended for navbars -->
  <VdThemeSwitcher align="end" @change="onChange" />
</template>
Cycle Button

Pass :menu="false" for a single button that cycles System → Light → Dark on each click — best for minimal apps where a one-click toggle beats a menu:

<!-- Single button that cycles System -> Light -> Dark -->
<VdThemeSwitcher :menu="false" />

The cycle button changes the theme immediately on each click, so it can flash between modes — prefer the menu in navbars.

VdThemeSwitcher vs VdThemeCustomizer
FeatureSwitcherCustomizer
Light / Dark / System mode
Per-theme primary defaults(follows scheme)
Palette selection (Open Color / Fibonacci) (via show-palette)
Primary color selection (18 colors)
Neutral scale (6 options)
Border radius (5 presets)
Font family (5 options)
FootprintToggle onlyFull panel
Use caseQuick toggleFull customization
Per-Theme Primary Defaults

The theme layer derives a default primary per scheme (PRIMARY_LIGHT / PRIMARY_DARK). Override them at bootstrap so switching modes swaps the accent automatically:

import { VanduoVue, setThemeDefaults } from "@vanduo-oss/vd3";

// Option A — pass themeDefaults to the plugin once, at bootstrap:
app.use(VanduoVue, {
  themeDefaults: {
    PRIMARY_LIGHT: "black",
    PRIMARY_DARK: "green",
  },
});

// Option B — call the helper directly, before the theme first reads defaults:
setThemeDefaults({ PRIMARY_DARK: "violet" });

While the primary is still one of these defaults, switching modes re-derives it. Once a user picks a specific color in the customizer, it sticks across mode changes.

API Reference

Props

PropTypeDescription
menubooleanIcon-menu variant, recommended for navbars (default true). When false, a single cycling button is rendered.
align"start" | "end"Menu alignment (default "start"). "end" aligns the dropdown to the toggle's trailing edge (adds .vd-theme-switcher-menu-end).

Events

EventPayloadDescription
changemode: "system" | "light" | "dark"Emitted whenever the user selects (menu) or cycles to (button) a mode.

CSS API

Class / AttributeDescriptionType
.vd-theme-switcherRoot wrapper for the icon-menu variant.Class
data-theme-ui="menu"Marks the menu variant; also .vd-theme-switcher-menu-end when align="end".Attribute
.vd-theme-switcher-toggleThe toggle button (and the standalone cycle button when menu=false).Class
.vd-theme-switcher-menuThe role="menu" popup holding the three mode options.Class
.vd-theme-switcher-optionA single role="menuitemradio" option; .is-active marks the current mode.Class
[data-theme-value]Set on each option to its mode value: system, light, or dark.Attribute
[data-theme-icon]Marks the toggle's Phosphor icon element that reflects the current mode.Attribute
data-theme="light|dark"Applied to <html> by the theme layer. Drives the CSS variable overrides; removed for system preference.State Attribute

localStorage Key

KeyDefaultValues
vanduo-theme-preferencesystemsystem, light, dark

The preference is persisted by the theme singleton and restored on the next load.

Best Practices

Use the Switcher when…

  • You only need a light/dark/system toggle
  • Navbar space is limited
  • Quick integration matters most

Use the Customizer when…

  • Users need color / neutral choices
  • Radius and font customization matter
  • You're building a theme-aware app

Use both when…

  • Quick toggle lives in the navbar
  • Full panel lives in settings
  • They coordinate through one singleton