/nuxt-color-mode

Primary LanguageTypeScriptMIT LicenseMIT

Nuxt Color Mode

npm version npm downloads License Nuxt

🌃 Dark and 🌞 Light mode with auto detection (even on server side!) made easy

This module is similar to the official module @nuxtjs/color-mode but with cookie support and server side system preference (via sec-ch-prefers-color-scheme header), making sure that the rendered theme on the server and client is always in sync.

It's not a 1:1 port of @nuxtjs/color-mode so expect a few API changes or missing features.

Features

  • 🚀  Full SSR support
  • 🍪  Cookie support
  • 🤖  Auto detect system color mode (even on server side!)
  • 🎨  Customizable
  • 🌪️  Temporary force color mode on individual pages or actions

Quick Setup

Install the module to your Nuxt application with one command:

npx nuxi module add @eschricht/nuxt-color-mode

That's it! You can now use Nuxt Color Mode in your Nuxt app ✨

Configuration

export default defineNuxtConfig({
  modules: ['@eschricht/nuxt-color-mode'],

  colorMode: {
    // The preferred mode when cookie hasn't been set yet
    preference: 'system',
    // Fallback to use when system preference is unavailable
    fallback: 'light',
    // Name to use when system preference is 'dark'
    systemDarkName: 'dark',
    // Name to use when system preference is 'light'
    systemLightName: 'light',
    // Prefix color mode class name
    classPrefix: '',
    // Suffix color mode class name
    classSuffix: '-mode',
    // Adds a data-attribute to the HTML.
    // Example, set it to 'color-mode' will add the HTML attribute 'data-color-mode="<color-mode>"'
    dataValue: '',
    // Name of the cookie
    cookieName: 'color-mode',
    // Cookie options
    cookieOptions: {},
  }
})

Composable

The composable returns a reactive object containing information about the current color theme.

Warning

Do not destruct the return value. Since it's a reactive object, reactivity will be lost.

Usage

<script setup lang="ts">
const colorMode = useColorMode()

console.log(colorMode.preference) // The current value stored in cookie, i.e. 'system'
console.log(colorMode.system) // The system preference, i.e. 'dark'. - Readonly
console.log(colorMode.value) // The resolved color mode, i.e. 'dark' or 'github-dark' if systemDarkName: 'github-dark' - Readonly

function changeColorMode() {
  colorMode.preference = 'some-other-value' // Updates cookie value and HTML class is set to `<html class="some-other-value-mode">`
}
</script>

Force color mode

It's possible to temporarily force the color mode on specific pages or situations. This can be done in 3 ways:

definePageMeta

<script setup lang="ts">
definePageMeta({
  colorMode: 'pink'
})
</script>

Composable

<script setup lang="ts">
const { forceColorMode } = useColorMode()

function handleError() {
  forceColorMode('error')
}

function resetError() {
  // Reset
  forceColorMode()
}
</script>

$colorMode.forcedValue

<template>
  <div>
    <button @click="$colorMode.forcedValue = 'pink'">FORCE 🌪️</button>
  </div>
</template>

Caveats

sec-ch-prefers-color-scheme is an experimental header and has limited browser support. The preferred color scheme is also fetched from browser API (client side only) as a fallback which can cause a flash of color change.

Contribution

Local development
# Install dependencies
pnpm install

# Generate type stubs
pnpm run dev:prepare

# Develop with the playground
pnpm run dev

# Build the playground
pnpm run dev:build

# Run ESLint
pnpm run lint

# Run Vitest
pnpm run test
pnpm run test:watch

# Release new version
pnpm run release