Skip to content

useColorMode

SSR-safe dark/light/system color mode. Cookie-backed, hydrates without FOUC.

Basic usage

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

<template>
    <button @click="toggle">
        {{ resolved === 'dark' ? '🌞 Light' : '🌙 Dark' }}
    </button>
    <p>Selected: {{ mode }} (resolves to {{ resolved }})</p>
</template>

API

ts
type ColorMode = 'light' | 'dark' | 'system';

interface UseColorModeReturn {
    /** Selected mode — may be 'system' to defer to OS preference */
    mode: WritableComputedRef<ColorMode>;

    /** Effective mode — always 'light' or 'dark', resolves system to OS */
    resolved: ComputedRef<'light' | 'dark'>;

    /**
     * Convenience boolean. Writable:
     *   isDark.value = true  → mode='dark'
     *   isDark.value = false → mode='light'
     */
    isDark: WritableComputedRef<boolean>;

    /** Flip light ↔ dark explicitly. Leaves 'system' unless re-selected via mode. */
    toggle: () => void;
}

SSR semantics

The mode is persisted in a cookie (vc-color-mode by default). On the server:

  • If the cookie is set to 'light' or 'dark', the SSR plugin emits class="light" or class="dark" on <html> immediately — no FOUC.
  • If the cookie is set to 'system' (or unset), the server cannot resolve the OS preference — there's no prefers-color-scheme available pre-hydration. The class is omitted; the client applies it on first render.

Once on the client, usePreferredDark from @vueuse/core watches the OS preference and mode resolves accordingly.

Configuration

In nuxt.config.ts:

ts
export default defineNuxtConfig({
    modules: ['@vuecs/nuxt'],
    vuecs: {
        colorMode: {
            cookieName: 'my-app-color-mode',
            value: 'dark',  // default for first-time visitors
        },
        // Color-mode cookie attributes. The palette cookie inherits
        // these unless `paletteCookie` is set explicitly.
        cookie: {
            sameSite: 'strict',
        },
    },
});

Use without Nuxt

@vuecs/design ships a framework-agnostic useColorMode() with the same return shape, persisting to localStorage instead of a cookie:

ts
import { useColorMode } from '@vuecs/design';
const { mode, resolved, isDark, toggle } = useColorMode();

The Nuxt-aware composable from @vuecs/nuxt is a thin wrapper over bindColorMode() from @vuecs/design — it swaps the storage layer for useCookie so the SSR plugin can read the same cookie at request time, but the apply / class-sync logic is shared.

See also

Released under the Apache 2.0 License.