CSS Variables & Theming Guide

Every colour, space, radius, and font in Vanduo is a CSS custom property (--vd-*). Override them in your own stylesheet and the whole system updates — no recompile, no JavaScript. This token layer ships with @vanduo-oss/vd3.

Global overrides
/* Override tokens in your own stylesheet — cascades everywhere */
:root {
  --vd-color-primary: #6366f1;
  --vd-color-primary-dark: #4f46e5;
  --vd-radius-fib-5: 0.5rem;
  --vd-font-family-base: 'Inter', sans-serif;
}
Scoped overrides

Custom properties cascade, so you can re-theme one subtree:

/* Scope overrides to a subtree — e.g. a "danger zone" panel */
.danger-zone {
  --vd-color-primary: var(--vd-color-danger);
}
The three token tiers
TierExamples
Palette--vd-blue-6, --vd-gray-0…9 — active scales (Open Color by default; --vd-oc-*/--vd-fib-* are the raw palette sources)
Semantic--vd-color-primary, --vd-bg-primary, --vd-text-primary, --vd-border-color
Component--vd-btn-border-radius, --vd-card-bg — per-component knobs

Semantic tokens reference palette tokens; component tokens reference semantic ones. Override at the tier that matches your intent.

Dark mode is the same mechanism
/* Dark mode just remaps the same token names */
[data-theme="dark"] {
  --vd-bg-primary: #0f1117;
  --vd-text-primary: #e6e8ee;
}

You rarely write this by hand — the theme customizer flips data-theme for you.

Bridge an app-owned toggle Vue 3

Already have a light/dark toggle (e.g. @nuxtjs/color-mode, a Pinia store, or your own ref)? The useThemeBridge composable from @vanduo-oss/vd3 keeps Vanduo in sync with it instead of adding a second source of truth.

import { computed } from 'vue';
import { useThemeBridge } from '@vanduo-oss/vd3';
import { useColorMode } from '@nuxtjs/color-mode'; // any owner of light/dark

// Vanduo keys dark mode off [data-theme] on <html>. When another system owns
// the toggle, hand it that system's mode ref and Vanduo follows along:
const colorMode = useColorMode();
useThemeBridge(computed(() => colorMode.preference));

// On mount and on every change, the bridge sets [data-theme] AND re-derives
// the default accent for the active scheme — no duplicate toggle UI needed.

Pass a Ref<'light' | 'dark' | 'system'>. The bridge re-syncs on mount and whenever the ref changes — useful for SSR / Nuxt apps where the host framework owns colour mode.