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
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
| Feature | Switcher | Customizer |
|---|---|---|
| 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) | |
| Footprint | Toggle only | Full panel |
| Use case | Quick toggle | Full 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
| Prop | Type | Description |
|---|---|---|
menu | boolean | Icon-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
| Event | Payload | Description |
|---|---|---|
change | mode: "system" | "light" | "dark" | Emitted whenever the user selects (menu) or cycles to (button) a mode. |
CSS API
| Class / Attribute | Description | Type |
|---|---|---|
.vd-theme-switcher | Root 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-toggle | The toggle button (and the standalone cycle button when menu=false). | Class |
.vd-theme-switcher-menu | The role="menu" popup holding the three mode options. | Class |
.vd-theme-switcher-option | A 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
| Key | Default | Values |
|---|---|---|
vanduo-theme-preference | system | system, 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