Tutorial - Crea un modo oscuro/claro para tu página web con React - Next.js

in Develop Spanish3 years ago (edited)

Hoy vamos a crear una función muy de moda en estos tiempos que es la de activar el modo claro/oscuro en nuestra página web, usaremos React con su Framework Next.js para ello.



Crearemos una carpeta en el escritorio de nombre toggle-dark-mode/

Una vez creado la carpeta navegamos hacia ella y ejecutamos


npm init --yes


Instalaremos los siguientes modulos:

npm i react react-dom next react-ios-switch


Es momento de codear

Crearemos una carpeta public/ y crearemos nuestras rutas (.js)

public/index.js

import Layout from "../components/Layout";
import Head from "next/head";
const index = () => {
  return (
    <>
      <Head>
        <title>
          Modo Oscuro | Claro en  Next.js  | Jfdesousa7 | tupaginaonline.net
        </title>
      </Head>
      <Layout>
        <div className="main-container">
          <h1>Toggle Dark Mode Next.js !!</h1>
        </div>
      </Layout>
    </>
  );
};
export default index;


public/about.js

import Layout from "../components/Layout";
import Head from "next/head";
const about = () => {
  return (
    <>
      <Head>
        <title>
          Modo Oscuro | Claro en  Next.js - About | Jfdesousa7 | tupaginaonline.net
        </title>
      </Head>
      <Layout>
        <div className="main-container">
          <h1>About</h1>
        </div>
      </Layout>
    </>
  );
};
export default about;


public/portfolio.js

import Layout from "../components/Layout";
import Head from "next/head";
const portfolio = () => {
  return (
    <>
      <Head>
        <title>
          Modo Oscuro | Claro en  Next.js - Portfolio | Jfdesousa7 | tupaginaonline.net
        </title>
      </Head>
      <Layout>
        <div className="main-container">
          <h1>Portfolio</h1>
        </div>
      </Layout>
   </>
  );
};
export default portfolio;


public/contact.js

import Layout from "../components/Layout";
import Head from "next/head";
const contact = () => {
  return (
    <>
      <Head>
        <title>
          Modo Oscuro | Claro en  Next.js - Contact | Jfdesousa7 | tupaginaonline.net
        </title>
      </Head>
      <Layout>
        <div className="main-container">
          <h1>Contact</h1>
          <br></br>
          <p><a className="link" href="https://hive.blog/@jfdesousa7">Jfdesousa7</a></p>
          <p><a className="link" href="https://tupaginaonline.net">tupaginaonline.net</a></p>
        </div>
      </Layout>
    </>
  );
};
export default contact;


Crearemos un archivo _app.js que es donde importaremos nuestros estilos personalizados

public/_app.js

import '../styles.css';
// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
    return <Component {...pageProps} />
  }


Crearemos en la raiz nuestro estilo .css

style.js

@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@300&display=swap');
:root {
  --font-family: 'Raleway', sans-serif;
}
*,
*::before,
*::after {
    margin : 0;
    box-sizing: border-box;
}
.theme-dark {
    --dark-text: #292929;
    --dark-background: #2F4550;
    --light-background: #586F7C;
    --accent: #b8dbd9;
    --button-border: #b8dbd9;
    --light-text: #F9F8F8;
  }
.theme-light {
    --dark-text: #5E4B56;
    --accent: #dbe7e4;
    --button-border: #5E4B56;
    --dark-background: #DBE7E4;
    --light-text: #5E4B56;
    --light-background: #EDDCD2;
  }
body {
    font-family: var(--font-family);
    background-color: var(--dark-background);
    color: var(--dark-text);
    height: 100vh;
    transition: all ease-in-out .7s;   
}
nav {
    background-color: var(--dark-background);
    color: var(--light-text);
    padding: 2em;
  }
  nav ul {
      display : flex;
      justify-content: space-between;
  }
  nav ul li {
      list-style: none;
  }
  nav ul li a {
      cursor: pointer;
      color: var(--light-text);
      font-weight: 800;
      text-decoration: none;
  }
.main-container {
    background-color: var(--light-background);
    padding: 4rem
}
.link {
    color: var(--light-text);
}
@media screen and (max-width:412px) {
    nav ul {
        display : flex;
        flex-direction: column;
        align-items: center;
        gap: 1em
    }
}


Componentes

components/Header.js

import Toggle from "../components/Toggle";
import Link from "next/link";
const Header = () => {
  return (
    <nav>
      <ul>
       <li>
          <Link href="/">
            <a>Inicio</a>
          </Link>
        </li>
        <li>
          <Link href="/about">
            <a>Nosotros</a>
          </Link>
        </li>
        <li>
          <Link href="/portfolio">
            <a>Portafolio</a>
          </Link>
        </li>
        <li>
          <Link href="/contact">
            <a>Contacto</a>
          </Link>
        </li>
        <li>
          <Toggle />
        </li>
      </ul>
    </nav>
  );
};
export default Header;


components/Layout.js

import { useEffect } from "react";
import { keepTheme } from "../utils/themes";
import Header from "./Header";
import Head from "next/head";
const Layout = ({ children }) => {
  useEffect(() => {
    keepTheme();
  });
  return (
    <>
      <Head>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <Header />
      {children}
    </>
  );
};
export default Layout;


components/Toggle.js

import { useEffect, useState } from "react";
import { setTheme } from "../utils/themes";
import Switch from "react-ios-switch";
export default function Toggle() {
  const [checked, setChecked] = useState(true);
  const handleOnClick = () => {
    if (localStorage.getItem("theme") === "theme-dark") {
      setTheme("theme-light");
      setChecked(false);
    } else {
      setTheme("theme-dark");
      setChecked(true);
    }
  };
  useEffect(() => {
    if(localStorage.getItem("theme")){
      if (localStorage.getItem("theme") === "theme-dark") {
        setChecked(true);
      } else {
        setChecked(false);
      }
    }else{
      setChecked(true);
    }
  }, []);
  return ( 
    <div className="light_dark">
      <label>
        <span className="">Modo light</span>
      </label>
      <Switch
        onColor="black"
        offColor="gold"
        checked={checked}
        onChange={handleOnClick}
      />
      <label>
        <span className="">Modo dark</span>
      </label>
    </div>
  );
}


Crearemos dentro una carpeta en la raiz llamada utils/ un archivo con dos funciones

utils/themes.js

export function setTheme(themeName) {
    localStorage.setItem('theme', themeName);
    document.documentElement.className = themeName;
}
export function keepTheme() {
  if (localStorage.getItem('theme')) {
    if (localStorage.getItem('theme') === 'theme-dark') {
      setTheme('theme-dark');
    } else if (localStorage.getItem('theme') === 'theme-light') {
      setTheme('theme-light')
    }
  } else {
    setTheme('theme-dark')
  }
}


Puedes probar el modo oscuro/claro en el link de abajo

click en el enlace https://dark-mode-jfdesousa7-next.herokuapp.com/


Y con esos amigos llegamos al final del tutorial, espero que lo hayan disfrutado y ¡hasta la próxima!


Visite mi sitio web oficial para presupuestos y mucho más

TupaginaOnline.net