Implementando Dark Mode en Gatsby con Sass (2/2)
JPGallegos1
Posted on January 29, 2020
Implementando Dark Mode en Gatsby con Sass |
---|
1) Integrando Sass en Gatsby |
2) Implementando dark mode con un custom hook y Sass |
Bienvenides a la segunda parte de la implementación del Dark Mode en Gatsby con Sass. En esta ocasión voy a arrancar definiendo variables y después crearemos un custom hook, el cual su lógica nos permitirá switchear entre fondo light
o dark
.
Definiendo variables
Dentro de nuestra carpeta sass
vamos a crear un archivo que voy a llamar _vars.scss
y dentro de éste voy a nombrar cuatro variables:
Background:
$bgLight: rgb(243, 241, 241);
$bgDark: rgb(32, 30, 30);
Colores:
$green: rgb(40, 168, 40);
$pink: rgb(243, 131, 237);
A saber: nombrar los archivos con _
al principio es una caracteristica de Sass y es conveniente que todos se nombren de esa forma menos el principal.
Lo siguiente que haremos es integrar nuestras variables al archivo principal layout.scss
y para ello escribiremos la siguiente línea de código: @import './vars';
. En este caso no hace falta que lleve extensión .scss
dado que lo reconoce automáticamente. Para testear que todo funcione, en nuestro layout.scss
escribiremos body{ background: $bgDark }
y tendríamos que ver nuestro fondo negro en localhost:8000
.
Finalmente a layout.scss
le haré unas modificaciones, modificaré pages/index.js
y agregaré _index.scss
a mi carpeta de Sass. Debería quedar de la siguiente manera:
En caso de tener un proyecto avanzado en Gatsby, asegúrate de que tu body reciba el &.dark{ background: $bgDark }
Creando el Custom Hook o Hook Personalizado
Como sabemos, en React tenemos distintos hooks como useState
, useEffect
o useContext
que permiten distintas funcionalidades, pero algo realmente bueno de React es la posibilidad de crear nuestros propios hooks para que hagan lo que nosotros queremos. Al fin y al cabo son funciones.
"¿Pero será muy difícil?": A un custom hook se le puede agregar toda la lógica y complejidad que se quiera, pero no va a ser este el caso. Crearemos algo sencillo, entendible para todes.
Primeros pasos con nuestro hook
Nos dirigimos a nuestra carpeta src
y creamos otra que la llamaré hooks
y dentro tendrá un archivo de nombre useTheme.js
.
A saber: la recomendación que nos da React es que nuestros hooks personalizados empiecen con use
.
Dentro de nuestro hook, debemos importar React
y el useState
. Crearemos la función useTheme
y la exportaremos para hacerla disponible en otros componentes.
Lo siguiente que haremos es crear un state
con value
y setValue
que arrancará en null
, junto a un método que voy a llamar handleTheme
, el cual voy a retornar y más adelante nos permitirá ejecutar el evento de nuestro botón. En un principio debería quedar así:
Nota: pueden obviar el import React...
y dejarlo de esta forma import {useState} from 'react'
. Eso eliminará una advertencia en la consola pero ambas formas son válidas.
Jugando con el DOM
si recuerdas, yendo a la consola y tipeando document
podemos acceder a todo nuestro HTML
. Entre todo ese árbol está el body
y dentro de éste elemento podemos ver si contiene o no clases. Incluso puedes tipear en la consola document.body
y luego intentar document.body.classList
para hacer todo más sencillo.
Complemento: la diferencia entre ClassName
y ClassList
es que el primero nos devuelve todas las clases que contenga un elemento en forma de string
y el segundo en un array
, lo cual ésta última opción nos permite agregar y quitar clases. Para saber más sobre esta diferencia aconsejo leer el primer comentario de este post.
Como nos interesa acceder a este último elemento, simplemente lo vamos a guardar en una constante así como esta: const body = document.body.classList
y debajo vamos a crear otra: const darkTheme = 'dark'
. Y estas son las dos únicas variables que vamos a requerir.
Implementando la lógica
Ahora, quizá esta puede ser la parte más confusa para muches. Pero primero lo primero: cuando algo confunde, lo mejor es escribir pseudo-código y plantear el problema en nuestro lenguaje, no en el de las computadoras.
CONSEJO: Lo que también nos permite la consola es ver todos los métodos con los que tenemos permitido interactuar por medio de su prototype:
De todos esos métodos, vamos a utilizar tres: contains()
, add()
y remove()
. Repasando rápidamente en nuestro lenguaje: si body
contiene la clase dark
if(body.contains()){ ... }
quiero que lo remuevas body.remove()
, de otra forma, agregala body.add()
. De momento nos quedaría algo así:
Hasta ahí perfecto; pero queremos más. Queremos combinarlo con nuestro state
y esa clase que se agrega y remueve por medio de un click quede guardada ahí. Vamos a hacer un setValue
al momento de agregar y quitar. Finalmente, hacemos un return { value, handleTheme }
para tenerlo disponible donde lo vayamos a utilizar.
GRAN TRABAJO! Ya tenemos nuestro custom hook finalizado. Ahora será momento de usarlo.
Utilizando nuestro Custom Hook
Ya hicimos la parte más complicada, ahora sólo queda disfrutar de lo logrado hasta aquí.
Como primer paso vamos a nuestro src/pages/index.js
e importamos nuestro hook personalizado tipeando import useTheme from '../hooks/useTheme'
. La siguiente que haremos es cortar todo el contenido dentro de const IndexPage = () => (...)
y reemplazarlo de la siguiente forma:
Lo siguiente es extraer la función de handleTheme
que implementamos y retornamos en nuestro useTheme.js
. Para eso, arriba del return ( ... )
vamos a escribir const {handleTheme} = useTheme();
. Por último, a nuestro botón le vamos a dar la funcionalidad de handleTheme
de la siguiente forma: <button onClick={handleTheme}>Moon</button>
.
¡Listo! Ya podemos switchear el background de nuestro sitio entre light o dark mode, porque si recuerdas, a nuestro body
ya le avisamos que iba a recibir la clase dark
y en nuestro hook personalizado hicimos la funcionalidad de agregarla y removerla a través de un evento onClick
.
Pequeño truco en Sass
Lo último que quiero enseñarte es un pequeño truco de Sass. Como sabemos, nosotros en nuestro index.scss
tenemos un h1{ color: $green }
. En ese mismo h1
y en realidad puede ser en cualquier selector o elemento, vamos a tipear body.dark & { color: $pink }
. Y eso cambiará el color de nuestro h1
o elemento con el que quisieramos hacerlo.
Agradezco inmensamente a aquelles que se tomaron el tiempo de leer estos artículos y ojalá les haya servido. En este link puede acceder al código final del proyecto. Dudas y sugerencias, todo es bienvenido en un comentario o me pueden escribir a mi twitter.
Posted on January 29, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.