Skip to content

Dark Mode ​

Dark mode in vuecs is class-based: toggle .dark on <html> (or any ancestor of your component tree), and the design-system tokens in @vuecs/design flip automatically.

How it works ​

In assets/index.css:

css
:root {
    --vc-color-bg:           var(--color-white);
    --vc-color-fg:           var(--vc-color-neutral-900);
    --vc-color-border:       var(--vc-color-neutral-200);
    /* ... */
}

.dark {
    --vc-color-bg:           var(--vc-color-neutral-900);
    --vc-color-fg:           var(--vc-color-neutral-200);
    --vc-color-border:       var(--vc-color-neutral-800);
    /* ... */
}

Only the semantic aliases flip. The numeric scales (--vc-color-primary-500, etc.) stay the same — your primary blue is the same blue in both modes.

Components use bg-bg, text-fg, border-border (and their tokenized equivalents in non-Tailwind themes), so they all flip together.

Configuring the variant ​

In your stylesheet, add the dark variant if you want to author dark-specific overrides:

css
@import "tailwindcss";
@import "@vuecs/design";

@custom-variant dark (&:where(.dark, .dark *));

This makes dark:bg-primary-700 and friends work in your own classes. (Component packages don't need it — they read tokens, which flip on their own.)

Toggle in vanilla Vue ​

Roll your own toggle, or use @vueuse/core's useDark:

vue
<script setup>
import { useDark } from '@vueuse/core';
const isDark = useDark();
</script>

<template>
    <button @click="isDark = !isDark">
        {{ isDark ? '🌞' : '🌙' }}
    </button>
</template>

useDark adds/removes the .dark class on <html> automatically.

Toggle in Nuxt ​

@vuecs/nuxt ships its own useColorMode() composable, SSR-safe and cookie-backed:

vue
<script setup>
const { mode, resolved, isDark, toggle } = useColorMode();
</script>

<template>
    <button @click="toggle">{{ resolved === 'dark' ? '🌞' : '🌙' }}</button>
</template>

The composable is auto-imported. The vc-color-mode cookie persists the user's choice; the SSR plugin reads it and emits class="dark" on <html> before first paint, so there's no FOUC.

If you'd rather use @nuxtjs/color-mode, set vuecs: { colorMode: false } in nuxt.config.ts to opt out and wire it yourself.

See useColorMode for the full API.

Custom palettes in dark mode (Tailwind only) ​

The .dark flip only changes semantic aliases. To repalette the whole UI in dark mode (e.g. cooler blues, warmer accents), call setColorPalette() from @vuecs/theme-tailwind after <html> gains the .dark class:

ts
import { setColorPalette } from '@vuecs/theme-tailwind';
import { watch } from 'vue';

watch(isDark, (dark) => {
    setColorPalette({
        primary: dark ? 'cyan' : 'blue',
    });
});

Next steps ​

Released under the Apache 2.0 License.