El modo oscuro es una de las funciones que se vería excelente implementado en tu aplicación, ya que mejoraría la experiencia de usuario dentro de tu aplicación.
Por lo que en esta ocasión, te enseñare como implementar el modo oscuro con React y sin alguna otra librería externa!
🚨 Nota: Este post requiere que sepas las bases de React con TypeScript (hooks básicos).
Cualquier tipo de Feedback es bienvenido, gracias y espero disfrutes el articulo.🤗
La idea es usar las variables con CSS para el tema dark y light.
🟡 Configurando las variables para el tema light.
Creamos una carpeta llamada src/styles y creamos el archivo var.css.
Este archivo se encargara de establecer las variables de CSS.
1- Para establecer las variables dentro de CSS usamos pseudo-clase root de la siguiente manera
:root{}
Dentro colocamos las variables que vamos a usar. Para definir variables utilizamos esta sintaxis
--background:#f2f2f2;
Tenemos que colocar doble guion antes del nombre personalizado de nuestra propiedad, luego, colocamos dos puntos y agregamos el valor de dicha propiedad.
Aquí están las demás variables:
Estas variables que acabamos de declarar sin para el tema light
🟡 Configurando las variables para el tema dark.
Ahora vamos a definir los variables para el tema oscuro.
Para ello, los nombres de las variables tienen que ser nombradas exactamente igual que las variables anteriores y solo cambiamos su valor después de los dos puntos.
Nota que para las variables de tema oscuro, ya no usamos la pseudo-clase root, sino que hacemos referencia a un atributo personalizado que estamos definiendo como theme.
Este atributo personalizado, tiene que colocarse en una etiqueta HTML para que el modo oscuro funcione (No coloque el atributo manualmente, esto se hará de forma dinámica, usando react).
Pero no en cualquier etiqueta, sino que, se debe colocar en la etiqueta de mayor jerarquía, como bor ejemplo el body.
Esto es un ejemplo de como debe verse
<bodydata-theme='dark'><!-- content --><body>
Si colocamos el atributo data-theme en el otra etiqueta con menos jerarquía, solo el contenido de esa etiqueta usara el modo oscuro.
Por esta razón, hay que colocarla en la etiqueta con mayor jerarquía.
<body><divdata-theme='dark'><!-- Dark theme --></div><div><!-- Light theme --></div><body>
🟡 Usando las variables en nuestros estilos.
Ahora, note que hemos creado un archivo var.css dentro de src/styles. Pero, ¿Donde las importamos?
Bueno, en mi caso me pareció, mejor importarlo en el archivo src/index.css.
Para importar archivos de .css en otro archivo .css usamos @import url() y agregamos la ruta donde se encuentra el archivo a importar.
Esto de separar los archivos CSS es buena practica ya que ayuda a entender mejor el código de los estilos.
Por cierto, debes colocar la importación en el top de tu archivo.
Para usar las variables, se hace uso de la función var() y dentro le colocamos el nombre de la variable exactamente como la nombramos en nuestro archivo var.css
Una vez que se hayan colocado las variables en los demás estilos (en las tarjetas, en el switch y el titulo), proseguiremos con agregar la lógica para cambiar entre temas.
💡 Agregando la lógica para cambiar entre temas.
Primero, tenemos que controlar el estado el switch para poder obtener cuando esta 'on' / 'off' y dependiendo de esos valores usar un tema u otro.
🟡 Controlando el estado del switch.
1- Primero agregamos un estado. Este estado sera de tipo Theme, y solo aceptara el string 'dark' o 'light'.
2- Creamos la función para controlar el evento del switch.
El cual nombramos handleChange, recibe como parámetro el evento que emite por defecto el input.
La función llama al setter setTheme y dentro hace una evaluación:
Si la propiedad checked del input esta en true, establece el tema 'dark'.
Si la propiedad checked del input esta en false, establece el tema 'light'.
Ahora, la función handleChange se va a ejecutar cuando el input de tipo checkbox tenga un cambio y por eso se lo pasamos a método onChange.
Y la propiedad checked del mismo input, le pasaremos una evaluación, ya que la propiedad checked solo acepta valores booleanos. La evaluación sera:
Si el el valor del estado theme es 'dark', el valor de checked sera verdadero.
Si el el valor del estado theme es 'light', el valor de checked sera falso.
3- Y ahora, recuerdan que íbamos a colocar el atributo personalizado data-theme, pues ahora toca hacerlo.
Para ello usamos un efecto, el cual debe ejecutarse cada vez que el valor del estado theme cambie. Es por eso que lo colocamos en su arreglo de dependencias del useEffect.
Después, dentro del useEffect ejecutamos lo siguiente:
document.body.setAttribute('data-theme',theme);
Básicamente, estamos accediendo a la etiqueta body (porque es el punto más alto que encierra toda nuestra aplicación), y le establecemos un nuevo atributo con la función setAttribute
setAttribute, recibe en este caso dos parámetros:
el nombre del nuevo atributo.
el valor para ese nuevo atributo.
Asi que, le establecemos el atributo data-theme con el valor del estado theme.
Y ahora definitivamente ya esta mas limpio y fácil de leer nuestro componente! 🥳
💡 Conclusión.
Todo el proceso que acabo de mostrar, es una de las formas en que se puede hacer la funcionalidad para crear el modo oscuro y cambiar entre temas, sin usar alguna librería externa. 🌙
Espero haberte ayudado a entender como realizar esta funcionalidad y que logres aplicarla en tus futuros proyectos, muchas gracias por llegar hasta aquí! 🤗❤️
Te invito a que comentes si es que conoces alguna otra forma distinta o mejor de como hacer esta funcionalidad. 🙌