How To Add Dark Mode Toggle in ReactJS + TailwindCSS + DaisyUI ⚛️🌼
Tags: react, tailwindcss, webdev, beginners
Published: 2023-04-26 18:31:47

{% youtube B-MzDlbxHRw %}

## Introduction:
In this tutorial, we will learn how to add a dark mode toggle with local storage persistence to a ReactJS + TailwindCSS + DaisyUI project. We will begin by setting up the project and installing the necessary dependencies. Next, we will create a Navbar and Hero component using DaisyUI's pre-built components. Finally, we will implement a dark mode toggle using DaisyUI's help and by updating the custom attribute in the HTML tag to add local storage persistence to it.

## Prerequisites:
Before we get started, you need to have the following tools and technologies installed on your machine:
- NodeJS
- Code Editor

## Initiate ReactJS project
Let's start by creating a new Reactjs project using the `create-react-app` command.
```bash
npx create-react-app dark-mode-toggle
cd dark-mode-toggle
```
Then remove the unnecessary files and code from the src directory.


## Installing and Configuring TailwindCSS
To install TailwindCSS, run the following command:
```bash
npm install -D tailwindcss
```
Then create a new file called `tailwind.config.js` by running the following command:
```bash
npx tailwindcss init
```
In the `tailwind.config.js` file, add the following code to it:

```javascript
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],

  theme: {
    extend: {},
  },
  plugins: [],
}
```
In your `src/index.css` file, add the following directives:
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

## Installing and Configuring DaisyUI
Now that we've set up TailwindCSS, let's install DaisyUI. DaisyUI is a collection of ready-to-use UI components designed to work seamlessly with TailwindCSS.

To install DaisyUI, run the following command in your project directory:
```bash
npm install daisyui
```
After the installation is complete, we need to configure DaisyUI with TailwindCSS.

Open the `tailwind.config.js` file and add the following code at the end of the plugins array:
```javascript
plugins: [require('daisyui')],
```
Now we also need to add the daisyUI themes so that we can switch between them.
```javascript
  daisyui: {
    themes: ["light", "dark"],
  },
```
The whole code in our `tailwind.config.js` file would look something like this:
```javascript
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],

  theme: {
    extend: {},
  },
  plugins: [require("daisyui")],
  daisyui: {
    themes: ["light", "dark"],
  },
}
```

## Navbar component
Now create an `Navbar.js` file inside the `src/components` folder and add the following code to it:

```react
import { useState, useEffect } from "react";

// assets
import logo from "../assets/om-logo.png";
import sun from "../assets/sun.svg";
import moon from "../assets/moon.svg";

const Navbar = () => {
  return (
    <div className="navbar bg-base-100 shadow-lg px-4 sm:px-8">
      <div className="flex-1">
        <img src={logo} alt="OM" className="btn btn-ghost p-0" />
        <h1 className="text-lg font-bold mx-4">Your Website</h1>
      </div>
      <div className="flex-none">
        {/* Toggle button here */}
        <button className="btn btn-square btn-ghost">
          <label className="swap swap-rotate w-12 h-12">
            <input type="checkbox" />
            {/* light theme sun image */}
            <img src={sun} alt="light" className="w-8 h-8 swap-on" />
            {/* dark theme moon image */}
            <img src={moon} alt="dark" className="w-8 h-8 swap-off" />
          </label>
        </button>
      </div>
    </div>
  );
};
export default Navbar;
```

### Hero component (Optional)
To add some content to our single page, let's create another component called `Hero.js` inside the `src/components` folder and add the following code it:
```react

const Hero = () => {
  return (
    <div className="hero min-h-full h-full pt-[20%]">
      <div className="hero-content text-center">
        <div className="max-w-md">
          <h1 className="text-5xl font-bold">Your Awesome Website!</h1>
          <p className="py-6">
            Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.
          </p>
          <button className="btn btn-primary">
            Checkout
          </button>
        </div>
      </div>
    </div>
  );
};
export default Hero;
```

## Adding Navbar and Hero components to App.js
Now we are ready to show our components in our single page by adding them to the `App.js` component as:
```react
import Navbar from "./components/Navbar";
import Hero from "./components/Hero";

function App() {
  return (
    <div className="h-full min-h-full">
      <Navbar />
      <Hero />
    </div>
  );
}

export default App;
```

## Implementing Dark Mode Toggle functionality
Towards the end, we have to toggle the dark/theme when we click on the toggle button from the Navbar component. So, add the following code to the `Navbar.js` component:
```react
import { useState, useEffect } from "react";

// assets
import logo from "../assets/om-logo.png";
import sun from "../assets/sun.svg";
import moon from "../assets/moon.svg";

const Navbar = () => {
  // use theme from local storage if available or set light theme
  const [theme, setTheme] = useState(
    localStorage.getItem("theme") ? localStorage.getItem("theme") : "light"
  );

  // update state on toggle
  const handleToggle = (e) => {
    if (e.target.checked) {
      setTheme("dark");
    } else {
      setTheme("light");
    }
  };

  // set theme state in localstorage on mount & also update localstorage on state change
  useEffect(() => {
    localStorage.setItem("theme", theme);
    const localTheme = localStorage.getItem("theme");
    // add custom data-theme attribute to html tag required to update theme using DaisyUI
    document.querySelector("html").setAttribute("data-theme", localTheme);
  }, [theme]);

  return (
    <div className="navbar bg-base-100 shadow-lg px-4 sm:px-8">
      <div className="flex-1">
        <img src={logo} alt="OM" className="btn btn-ghost p-0" />
        <h1 className="text-lg font-bold mx-4">Your Website</h1>
      </div>
      <div className="flex-none">
        {/* Toggle button here */}
        <button className="btn btn-square btn-ghost">
          <label className="swap swap-rotate w-12 h-12">
            <input
              type="checkbox"
              onChange={handleToggle}
              // show toggle image based on localstorage theme
              checked={theme === "light" ? false : true}
            />
            {/* light theme sun image */}
            <img src={sun} alt="light" className="w-8 h-8 swap-on" />
            {/* dark theme moon image */}
            <img src={moon} alt="dark" className="w-8 h-8 swap-off" />
          </label>
        </button>
      </div>
    </div>
  );
};
export default Navbar;
```

## Conclusion:
Congratulations! You've successfully added a dark mode toggle to your ReactJS application using Tailwind CSS and daisyUI. Now your users can enjoy the flexibility of choosing their preferred theme for a better user experience.

Thanks for following along, and happy coding!❤️