How to add the Toggle Theme in Next.js 15 using Zustand and TailwindCSS

Β·

4 min read

User prefer to use different theme on websites and application. It’s better to have different Theme Mode according to the user preferences. Today, we will see how to implement such Theme Mode change feature in your website.

We are going to implement this feature in Next.js 15 with the help of Zustand (State Manage Tool) and Tailwind CSS. We will walk through how to implement Toggle theme in application.


Setting up the Project

To get started, we need to Next.js application with Tailwind.css Configured along with Zustand state management Library. You can use following command to create Next.js application with TailwindCss.

npx create-next-app@latest project-name
cd project-name

Above query creates Next.js Application. Run a below query in command line to Integrate Tailwind CSS with Next.js.

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Now, Install Zustand in your application by simply running the below query.

npm install zustand immer persist

immer and persist are middleware libraries which are used in new version

Configured Files

Once application is create and Install all the required packages with need to configure files to complete Integration.

Modify the file tailwind.config.ts by replacing the entire code.

// tailwind.config.js

import type { Config } from 'tailwindcss'

export default {
  content: [
    './app/**/*.{js,ts,jsx,tsx,mdx}', // Note the addition of the `app` directory.
    './pages/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',

    // Or if using `src` directory:
    './src/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
} satisfies Config

You will see the global.css file replace the content with below code.

@tailwind base;
@tailwind components;
@tailwind utilities;

Along with add below content in tsconfig.json to setup Zustand.

// tsconfig.json
{
  "compilerOptions": {
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

Implementing Toggle Theme

Next.js makes it easy to implement toggle theme with Tailwind CSS. You can declared classes by pretending dark: to the properties to indicate that they are dark Mode. For example, you can use dark:bg-gray-900 to change the background color to gray-900 when the theme is set to dark.

By default, Next.js uses the system preferences to set the theme. However, we also need to toggle between light and dark modes. To do this, we can set the darkMode strategy to class in the tailwind.config.js file:

module.exports = {
  darkMode: 'class',
  // ...
}

With this configuration, Tailwind CSS will apply the theme when the dark class is present in the HTML tree.

Using Zustand to Create toggle Theme

Zustand is a state management library for React apps that helps manage and update application state. It's a lightweight, fast, and scalable tool that can be used to create and update global states.

To implement state management we need to create store in Next.js

  • Create store folder inside app directory inside your project

  • Inside store folder create a File name as Theme-Store.ts

// Theme-Store.ts
import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
import { persist } from "zustand/middleware";

export interface ThemeProp {
  themeMode: "light" | "dark";
  toggleTheme: (theme: string) => void;
}

export const useThemeStore = create<ThemeProp>()(
  persist(
    immer((set) => ({
      themeMode: "dark",

      toggleTheme(theme: string) {
        const newTheme = theme;
        if (newTheme === "dark") {
          set({ themeMode: "dark" });
        } else {
          set({ themeMode: "light" });
        }
      },
    })),
    {
      name: "theme",
    }
  )
);
  • Create a components Folder inside which create ThemeBtn.tsx

  • Copy the below code in ThemeBtn.tsx

"use client";
import { Moon, Sun } from "lucide-react";
import { useEffect, useState } from "react";
import { useThemeStore } from "@/stores/theme-store";

export default function Header() {
  const [themeMode, setThemeMode] = useState("dark");

  const { toggleTheme } = useThemeStore();

  const handleClick = () => {
    const newMode = themeMode === "dark" ? "light" : "dark";
    setThemeMode(newMode);
    toggleTheme(newMode);
  };

  useEffect(() => {
    document.querySelector("html")?.classList.remove("light", "dark");
    document.querySelector("html")?.classList.add(themeMode);
  }, [themeMode]);

  return (
    <div className="dark:bg-black bg-white text-black dark:text-white ">
      <div className="flex m-3 mx-6 justify-between items-center">
        <div
          className=" dark:hover:bg-gray-800 hover:bg-gray-200 rounded-xl p-2"
          onClick={handleClick}
        >
          {themeMode === "dark" ? <Moon /> : <Sun />}
        </div>
      </div>
    </div>
  );
}

Import the ThemeBtn.tsx inside page.tsx and now your application is good to go. Dark and Light theme is implemented.

Conclusion

I hope this article has helped you in implementing Toggle Theme.

Happy Coding πŸ‘¨β€πŸ’». Do like and share the Post.

Also Check out My Blog Innoveda

Β