A color scheme module developed for Nuxt
This module provides a comprehensive solution for managing color schemes in Nuxt applications, designed with simplicity and efficiency in mind. As such, it follows a minimalist approach and doesn’t offer extensive configuration, but instead focuses on simplicity and efficiency.
The module follows the philosophy and principles described in the article "From System Preferences to User Choice: Color Scheme Options in Modern Web Development", prioritizing user choice and system preferences while maintaining an intuitive and accessible user experience.
The module is open source, and available for the developer community to use, contribute to, and improve. If there’s interest from third parties, they can freely explore it and use it in their own projects without any issues.
This module implements a comprehensive color scheme strategy with the following key features:
Unlike most front-end tools (such as Tailwind, for example), which fundamentally define light
scheme as primary scheme, and dark
as the secondary one that requires an extra class, this module provides the ability to specify which should be the leading color scheme, and which should be the additional one.
This setting determines the name of the CSS class for the additional color scheme, which should be placed on the <html>
element when it’s active. The default value of this setting is the light
scheme, which makes integration with Tailwind possible.
This setting (enabled by default) provides the ability to specify whether the project will take into account the system color scheme and accordingly whether it will be an available option in the list of color scheme modes, between which the user will be able to make a choice. When enabled, the system
option will be added to the available light
and dark
modes.
It is important to note that when this option is enabled, it will work provided that the client environment itself supports system-level color schemes. If not, then the list of the available modes will remain with the two options only.
The module is designed to work with Sec-CH-Prefers-Color-Scheme
(when possible, of course), by passing the header over the network, so that based on the received context, the corresponding values can be prepared at the server-side rendering level.
At the time of development, it is known that Firefox and Safari do not support Sec-CH-Prefers-Color-Scheme.
Instead of localStorage
, the module creates a cookie to store specific scheme preferences different from system settings. This is intentional to ensure the cookie is part of request headers, so that based on the received context, the corresponding values can be prepared at the server-side rendering level.
The module is built based on the following hierarchy of priorities, arranged in descending order:
1. Cookie value
2. System value
3. Primary value
-
If the client’s system has a saved cookie with a color scheme value, this means that the corresponding color scheme has been explicitly specified by the user as permanent (until further notice) and this makes it the final active scheme.
-
If there is no saved cookie with a color scheme specified by the user, then the next possible active scheme comes from the system ones. This, of course, in the case that: both the system itself supports color schemes, and the project itself is configured to work with them.
-
As a last resort, if there is neither a saved cookie nor an available system color scheme, the specified primary scheme is taken as the active one.
Install the module to your Nuxt application with one command:
npx nuxi module add @mevbg/nuxt-color-scheme
This will download the module and add it automatically to the list of modules declared in the Nuxt configuration file, as shown in the following example:
export default defineNuxtConfig({
modules: ['@mevbg/nuxt-color-scheme']
});
That’s it!
You can now use Nuxt Color Scheme
in your Nuxt app. ✨
The module is subject to configuration, which can look like this:
export default defineNuxtConfig({
modules: ['@mevbg/nuxt-color-scheme'],
colorScheme: {
primaryScheme: 'light' // 'light' | 'dark'
systemScheme: true // true | false
}
});
More information about the possible settings is described in the following lines.
The module provides only these two settings:
Sets the primary color scheme ( 'light'
| 'dark'
).
- Type:
string
(optional) - Default:
'light'
- Description: This option determines whether a class will be applied to the HTML element for the currently selected scheme that differs from the primary one. The logic assumes that CSS styles relying on this approach will have colors for the primary color scheme defined outside class-based selector. For example, if it’s
'light'
, all colors won't be within thehtml.light
block scope, and the module won't apply thelight
class to the HTML element when the light scheme is selected. Instead, it will only apply thedark
class to trigger the defined CSS colors for the dark scheme within thehtml.dark
block scope.
Enables system preference detection.
- Type:
boolean
(optional) - Default:
true
- Description: This option plays a role in determining what switching options are provided by the
useColorScheme
composable. When enabled (as it is by default) and if the client’s system allows it (with appropriate checks), the composable will return three available modes:light
,dark
, andsystem
.
The useColorScheme
composable is automatically imported in the Nuxt environment and can be used directly without any manual imports.
const {
// Color scheme definitions
primary,
secondary,
// System-color-scheme-related data
serverSideSystemScheme,
clientSideSystemScheme,
clientSystemSupport,
appSystemSupport,
systemSupport
systemColorScheme,
// Current states
currentColorScheme,
currentMode,
currentClassName,
availableModes,
// Methods
setColorSchemeMode
} = useColorScheme();
Here is information about all the values and methods that this composable provides:
- Type:
ref<ColorSchemeKey>
- Default:
'light'
- Description: Stores the name of the primary color scheme. If such is not provided through the configuration object, the value remains the default set for the module.
- Type:
computed<ColorSchemeKey>
- Default:
'dark'
- Description: A reactive value that stores the name of the color scheme that is opposite to the primary one.
- Type:
ref<boolean | null>
- Default:
null
- Description: Sets value to
true
if it detects a system color scheme at the server level through theSec-CH-Prefers-Color-Scheme
header.
At the time of development, it is known that Firefox and Safari do not support Sec-CH-Prefers-Color-Scheme.
- Type:
ref<boolean | null>
- Default:
null
- Description: Sets value to
true
if it detects a system color scheme at the client level through thewindow.matchMedia
method.
- Type:
computed<boolean | null>
- Default:
null
- Description: A reactive value that is
true
if at least one of the above two (serverSideSystemScheme
/clientSideSystemScheme
) istrue
.
- Type:
ref<boolean>
- Default:
true
- Description: Stores the flag whether the app itself should work with the system color scheme (if such is available). If no setting is provided through the configuration object, the value remains the default set for the module.
- Type:
computed<boolean | null>
- Default:
null
- Description: A reactive value that is
true
if at least one of the above two (clientSystemSupport
/appSystemSupport
) istrue
.
- Type:
ref<ColorSchemeKey | undefined>
- Default:
undefined
- Description: Stores the name of the current system color scheme (if such). It gets updated when the system color scheme changes.
- Type:
ref<ColorSchemeKey>
- Default:
primary.value
- Description: Stores the name of the current color scheme applied to the app.
- Type:
ref<ColorSchemeMode>
- Default:
primary.value
- Description: Stores the name of the current color scheme mode.
- Type:
ref<string>
- Default:
''
- Description: Stores the string with the CSS class name (if such) that should be set to the
<html>
element.
- Type:
computed<ColorSchemeMode[]>
- Description: A reactive array containing the names of the available color scheme modes. If
systemSupport
istrue
the options includessystem
as well.
Here are the main TypeScript definitions:
// List of constant color schemes
export const colorSchemes = ['light', 'dark'] as const;
// List of possible color scheme modes, including the 'system' one
export const possibleColorSchemeModes = ['system', ...colorSchemes] as const;
// Type for names of color schemes
export type ColorSchemeKey = (typeof colorSchemes)[number];
// Type for names of color scheme modes
export type ColorSchemeMode = (typeof possibleColorSchemeModes)[number];
// The module options interface
export interface ColorSchemeOptions {
primaryScheme?: ColorSchemeKey;
systemScheme?: boolean;
}
# Install dependencies
npm install
# Generate type stubs
npm run dev:prepare
# Develop with the playground
npm run dev
# Build the playground
npm run dev:build
# Run ESLint check
npm run lint:check
# Run ESLint fix
npm run lint:fix
# Run Prettier check
npm run prettier:check
# Run Prettier fix
npm run prettier:fix
Contributions, suggestions, and improvements are welcome! Feel free to open issues or submit pull requests.