Cookies
This website uses cookies to improve the user experience, more information on the legal information path.
Notas
0
años
0
meses
0
días
0
horas
0
minus
0
segus
sáb16mar20:16
Esta es la imagen de fondo
2

Tema oscuro con Nextjs

vie, 3 feb 2023

Hay muchas formas de hacer la gestión de temas de estilos en React y Nextjs, pero todas ellas pasan por tener un array/objecto con todos los estilos de cada uno de los distintos temas, también otra de las formas es usar variables de css o scss estas últimas están en cada vez en más deshuso. Yo, en particular voy a usar variables de css y fijar un tema por defecto en mi _document . ¿ Por qué aquí ?

Por que _document se ejecuta en servidor no como _app que lo hace en cliente y si usas un useEffect para setear tu tema por defecto o detectar el que tiene el usuario en su sistema operativo, en el tiempo que se tarda en hacer esta comprobación y añadirlo, puede darse un parpadeo en los estilos de la pagina. Eso puede resultar extraño.

Yo lo hice así:

1 - Variables de css

globals.css

:root {
/* commons */
--white-color: 255, 255, 255;
--color-available-arrow: 95, 91 98;
...;
}
[data-theme='dark'] {
--blog-nav: 48, 41, 51;
--blog-header: 53, 45, 55;
...;
}
[data-theme='light'] {
--blog-nav: 204, 202, 219;
--blog-header: 255, 255, 255;
...;
}

2 - Fijar tema por defecto

_document.tsx

const Document = (props: Props) => {
return (
<Html lang={props.__NEXT_DATA__.locale} data-theme="light">
)
}

3 - Custom hook para cambiar el tema

useDarkMode.ts

import React from 'react';
const scheme = {
light: 'light' as const,
dark: 'dark' as const,
};
const useDarkMode = (): { theme: null | 'dark' | 'light'; toggleTheme: () => void; scheme: typeof scheme } => {
const [theme, setTheme] = React.useState<null | 'dark' | 'light'>(null);
React.useEffect(() => {
if (typeof window !== 'undefined' && window.matchMedia) {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handler = (event: MediaQueryListEvent) => {
setTheme(event.matches ? scheme.dark : scheme.light);
};
mediaQuery.addEventListener('change', handler);
return () => mediaQuery.removeEventListener('change', handler);
}
}, []);
React.useEffect(() => {
if (typeof window !== 'undefined' && theme) {
document.documentElement.setAttribute('data-theme', theme);
}
}, [theme]);
const toggleTheme = () => {
setTheme(theme === scheme.dark ? scheme.light : scheme.dark);
};
return { theme, scheme, toggleTheme };
};
export default useDarkMode;

4 - Usar el hook

settings.tsx

const Content = () => {
const { formatMessage: f } = useIntl();
const {
theme,
scheme: { dark },
toggleTheme,
} = useDarkMode();
return (
<div className={styles.container}>
<section className={styles.confg}>
<IconWithName
icon="/theme.png"
alt={f({ id: 'settings.langAlt' })}
name={f({ id: theme === dark ? 'settings.dark' : 'settings.light' })}
onClick={toggleTheme}
/>
</section>
<section className={styles.confg}></section>
</div>
);
};

Para hacer la prueba en vivo, puedes cambiar el tema en tu sistema operativo y verás que mi sitio web se actualiza automáticamente o también puedes ir a mi pagina de configuración y cambiar el tema.

Todo el código en mi repositorio de github, si te gusta este proyecto, o si el contenido te ha ayudado en algo puedes recompensarme con una ⭐️, Gracias!