¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
Conoce nuestra marca.¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
Conoce nuestra marca.dev
Jaime Fernández Moreno 28/11/2024 Cargando comentarios…
El modo oscuro es una característica cada vez más demandada en aplicaciones y sitios web modernos. Sencillamente, consiste en permitir cambiar el esquema de color de la aplicación, que puede elegir entre claro y oscuro.
En los orígenes de la informática, donde se utilizaban monitores CRT, el tema oscuro era la única opción ya que estas pantallas mostraban texto verde sobre fondo negro. Más tarde, con la evolución de las interfaces gráficas, el tema claro se convirtió en el estándar predominante.
Más recientemente ha habido un resurgimiento del modo oscuro. Twitter en 2017 lo introdujo en su aplicación y más tarde le siguieron YouTube, MacOS, Android, iOS, etc. Hoy en día es un estándar en casi cualquier aplicación y sus beneficios incluyen:
Aunque haya gente a favor y en contra, lo mejor es poder elegir y tener la opción de cambiar entre tema claro y oscuro cuando queramos. En este artículo vamos a explicar cómo se puede implementar el modo oscuro de forma muy sencilla en una aplicación creada con Next.js y en la que estamos utilizando TailwindCSS para los estilos.
Vamos a utilizar las siguientes herramientas y dependencias, por lo que es conveniente conocerlas y haber trabajado con ellas:
Para controlar el estado de la selección del tema utilizaremos la biblioteca “next-themes”.
Creamos nuestra aplicación Next.js utilizando el siguiente comando, tal y como nos dice la propia documentación oficial del framework:
npx create-next-app@latest
Aquí nos hará una serie de preguntas. Lo importante es que digamos que sí a la pregunta de TailwindCSS y también a la del app router si queremos utilizar Next.js con las últimas características. Una vez finalizada la configuración inicial, si ejecutamos npm run dev y accedemos a localhost:3000 podremos ver la siguiente página:
Como hemos respondido que sí a la pregunta de TailwindCSS, el proyecto ya se va a crear con todas las dependencias instaladas y la configuración correcta. En caso de que partiéramos de un proyecto que no tuviera TailwindCSS y quisiéramos añadirlo, bastaría con seguir estos pasos de la documentación oficial de TailwindCSS.
En este punto vamos a preparar nuestra página con un contenido muy sencillo para entender mejor el ejemplo:
Necesitamos eliminar todo el contenido del globals.css excepto las directivas de TailwindCSS:
@tailwind base;
@tailwind components;
@tailwind utilities;
Después, nos vamos a app/page.tsx y sustituimos el contenido que devuelve nuestro componente por el siguiente código:
<main className="flex min-h-screen flex-col items-center justify-between p-24 bg-white dark:bg-black">
<h1 className="text-black dark:text-white">Ejemplo modo claro/oscuro</h1>
</main>
En este punto, el modo oscuro está habilitado pero de forma automática. Para poder controlarlo mediante un botón necesitamos añadir la opción darkMode: 'class', al fichero de configuración tailwind.config.ts dentro del objeto config.
De esta forma estará disponible en todas las utility classes de Tailwind el modificador dark:,. Así, cuando añadamos este modificador a una clase de un elemento, esto significará que dicha clase solo estará activa para el modo oscuro.
En este punto ya podemos ver cómo quedaría el dark mode en nuestra página, añadiendo la clase dark en el className de nuestro html.
<html className="light" lang="en">
<html className="dark" lang="en">
Haciendo este cambio en el html podremos ver en el navegador cómo cambia el tema de nuestra aplicación.
Ya tenemos la configuración de Tailwind necesaria, pero nuestro objetivo es que se pueda seleccionar entre el modo oscuro y el modo claro con un botón.
Para esto vamos a utilizar “next-themes”. Esta biblioteca nos va a proporcionar un componente ThemeProvider que nos va a facilitar todas estas cosas:
Si no utilizáramos next-themes, tendríamos que implementar toda esta lógica.
Para empezar, instalamos next-themes:
npm install next-themes
Una vez instalado, vamos a utilizar dos elementos:
"use client";
import { ThemeProvider as NextThemesProvider } from "next-themes";
import { type ThemeProviderProps } from "next-themes/dist/types";
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return (
<NextThemesProvider
themes={["light", "dark"]}
{...props}
>
{children}
</NextThemesProvider>
);
}
Es necesario crearlo como un componente aparte para luego utilizarlo desde nuestro layout, ya que este ThemeProvider de next-themes debe ser un componente renderizado en el cliente. De esta forma, desde el layout importaremos este componente y no tendremos que hacer todo el layout renderizado en el cliente.
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { ThemeProvider } from "@/components/ThemeProvider";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en" suppressHydrationWarning>
<body className={inter.className}>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
</body>
</html>
);
}
Podemos ver que tiene tres configuraciones:
Una vez que tenemos preparado esto, vamos a añadir un botón que nos permita cambiar entre temas.
Necesitamos el hook useTheme de la librería next-themes y lo utilizaremos de la siguiente manera en nuestro page.tsx:
"use client"
import { useTheme } from "next-themes";
import { useEffect, useState } from "react";
export default function Home() {
const { theme, setTheme } = useTheme();
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24 bg-white dark:bg-black">
<h1 className="text-black dark:text-white">Ejemplo modo claro/oscuro</h1>
Está activo el tema: {theme}
<button onClick={() => { setTheme(theme === 'light' ? 'dark' : 'light') }}>Cambiar tema</button>
</main>
);
}
Ya podemos comprobar que, al pulsar en el botón, vamos alternando entre los dos temas light y dark.
Como mejora añadida, vamos a solucionar un warning que nos debe aparecer en consola una vez que hemos llegado a este punto.
El error se llama Hydration Mismatch y consiste en que, dado que la información del tema actual (o del tema del sistema) se obtiene en el cliente, cabe la posibilidad de que estemos intentando renderizar el state light o dark antes de que se conozca esta información. Para solucionarlo tenemos que evitar que este componente que contiene el useTheme se renderice hasta que ese código no se esté ejecutando en el cliente.
Basta con añadir un useEffect con un estado mounted:
const { theme, setTheme } = useTheme();
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) {
return null;
}
Tenemos que añadir este useEffect y que, al ejecutarse (solo en la primera carga de la página), ponga a “true” este estado mounted. Y aquí, condicionar que se renderice el componente solo cuando el estado mounted sea “true”.
Si queremos que el botón del ejemplo no se vea como un simple texto, podemos añadirle las siguientes clases:
text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-100 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700
A lo largo de este artículo, hemos explorado cómo integrar el modo oscuro en una aplicación creada con Next.js utilizando next-themes y Tailwind CSS. Hemos repasado la configuración inicial del proyecto, la instalación y configuración de Tailwind CSS. A continuación, hemos visto la integración de next-themes para el manejo de temas y, por último, la creación de un componente de toggle para alternar entre el modo claro y oscuro.
Espero que este método os sea de utilidad a la hora de añadir el modo oscuro a vuestras aplicaciones.
Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.
Cuéntanos qué te parece.