Skip to content

Modo Claro / Oscuro

Es una funcionalidad que permite establecer toda la página web a modo claro o modo oscuro.

Índice

  1. Variables y Constantes.
  2. Store.
  3. Componente de vue.
  4. Aplicar en css.

Archivos que se requieren: - colors.ts : contiene constantes de colores. - mode.ts : contiene constantes de modo. - Mode.client.ts : contiene variables de colores. - Mode.global.ts : guarda el modo en localStorage. - mode.js : store que gestiona el modo. - DayNight.vue : componente para importar el boton de cambio de modo.

Variables y constantes

Constantes

Se crea un archivo colors.ts donde se van a declarar los colores que se van a utilizar en la página.

Se crean constantes para cada color de la paleta de colores.

export const useWhiteColor = () => useState<String>("cWhite", () => "#ffffff");
export const useBlackColor = () => useState<String>("cBlack", () => "#000000");
export const useLightGray = () =>
useState<String>("cLightGrey", () => "#f0f0f0");

Además se crea un objeto que contiene los colores para el modo claro y el modo oscuro.

Cada modo tiene los mismos nombres para cada color que se va a utilizar pero con distinto color, esto en función del modo se usa un color u otro.

export const modes = {
dark: {
cWhite: "#ffffff",
cBlack: "#000000",
cLightGrey: "#f0f0f0",
},
light: {
cWhite: "#000000",
cBlack: "#ffffff",
cLightGrey: "#f0f0f0",
},
};

Tambien, se crea un archivo mode.ts que contiene la constante de cada modo.

export const MODE = "mode";
export const LIGHT_MODE = "light";
export const DARK_MODE = "dark";

Variables

El archivo Mode.client.ts sirve para crear variables de color donde se va a almacenar el color que se va a usar dentro del css. Cada variable de color se actualiza si detecta que el modo se ha cambiado y obtiene el color del objeto modes y devuelve el color del modo que se le pase.

export default defineNuxtPlugin((nuxtApp) => {
// Se obtiene la variable reactiva del modo del Store
const { getMode } = storeToRefs(useModeStore());
const root = document.documentElement;
// Se define la función que establece la variable que se va a usar en el css
const setMode = (mode: ModeType) => {
// Se establece el nombre que se va a usar en el css (--c-white) y se le guarda el color
root.style.setProperty("--c-white", modes[mode].cWhite);
root.style.setProperty("--c-black", modes[mode].cBlack);
root.style.setProperty("--c-light-grey", modes[mode].cLightGrey);
};
setMode(getMode.value as ModeType);
// Cuando se cambia de modo se ejecuta setMode()
watch(getMode, () => setMode(getMode.value as ModeType));
});

Store

Se utiliza una store para almacenar el modo y que el modo cambie de forma reactiva, actualizando todos los componentes al cambiar el modo.

Se crea un archivo mode.js donde se va a almacenar el modo y se va a actualizar de forma reactiva.

export const useModeStore = defineStore("mode", () => {
// Declarar variable
const mode = ref(DARK_MODE);
// Crear un getter para obtener el modo
const getMode = computed(() => mode.value);
// Crear una función que cambie entre modo claro y oscuro
const changeMode = () => {
mode.value = mode.value === DARK_MODE ? LIGHT_MODE : DARK_MODE;
localStorage.setItem(MODE, mode.value);
};
// Función pra establecer el modo
const setMode = (newMode) => {
mode.value = newMode;
};
return { getMode, changeMode, setMode };
});

Además, en el archivo mode.global.ts se utiliza el localStorage para almacenar la preferencia del usuario y cada vez que entre en la página se carga el modo de la ultima vez, si es la primera vez que entra en la página se le crea y se le aplica por defecto el modo oscuro.

export default defineNuxtRouteMiddleware((to, from) => {
const { setMode } = useModeStore();
// Obtener el item del localStorage
const mode = localStorage.getItem(MODE);
if (!mode) {
// Si no existe el item se crea y se establece modo oscuro
setMode(DARK_MODE);
localStorage.setItem(MODE, DARK_MODE);
} else if (mode === DARK_MODE || mode === LIGHT_MODE) setMode(mode);
else localStorage.setItem(MODE, DARK_MODE);
});

Componente de vue

Para crear el boton de cambio de modo se crea un componente de vue DayNight.vue en el cual se crea un bloque que al pulsar encima se ejecuta la función de la store “changeMode” para que se cambie de modo.

Además, el bloque contiene otros componente que son svg que cambia en función del modo.

<script setup>
import { useModeStore } from '@/stores/mode'
import { storeToRefs } from 'pinia'
import { LIGHT_MODE, DARK_MODE } from '@/constants/mode'
const Sun = defineAsyncComponent(() => import('@/components/svg/Sun.vue'))
const Moon = defineAsyncComponent(() => import('@/components/svg/Moon.vue'))
// Se define el método para obtener el modo en el que se encuentra
const { getMode } = storeToRefs(useModeStore())
// Se define el método para cambiar de modo
const { changeMode } = useModeStore()
</script>
<template>
<div class="switch-mode" @click="changeMode">
<Transition name="mode-transition">
<Sun v-if="getMode === LIGHT_MODE" :width="'2em'" :height="'2em'" />
<Moon v-else-if="getMode === DARK_MODE" :width="'2em'" :height="'2em'" />
</Transition>
</div>
</template>

Aplicar colores en función del modo.

Para aplicar los colores en el proyecto se puede aplicar de dos formas distintas, una pasando el color por props o aplicando directamente en el css.

Pasar por props

Para pasar el color por props, primero hay que declarar los colores que se van a usar, por ejemplo:

const blackColor = useBlackColor();
const whiteColor = useWhiteColor();

También, hay que definir la funcion “getMode” de la store y hay que utilizar storeToRefs para que sea reactivo.

import { useModeStore } from "@/stores/mode";
import { storeToRefs } from "pinia";
import { DARK_MODE } from "@/constants/mode";
const { getMode } = storeToRefs(useModeStore());

Con esto se usa un condicional ternario que comprueba si se está en el modo oscuro y devuelve un color u otro.

:bgColor="getMode === DARK_MODE ? blackColor : whiteColor"

Aplicar en css

La otra manera para aplicar colores que en función del modo se cambie automaticamente, es aplicando directamente en el css.

Para esto, en la propiedad css que queramos aplicar un color, se usa var() y dentro indicamos el color del archivo Mode.client.ts que se ha definido.

color: var(--c-white);