reactjstailwind-cssthemesstyled-components

My react and tailwind app are applying the class but the style does not change


I have theme change functionality in my app using context. The theme (dark/light) class is being applied, but the colors don't change. I don't know if it's my tailwind config because when I try to type the "bg-primary" in the header, the autocomplete doesn't show the primary var, or it's the ThemeContext logic.

ThemeContext.tsx

    import React, { Dispatch, SetStateAction, ReactNode } from "react";

const getInitialTheme = () => {
    if (typeof window !== "undefined" && window.localStorage) {
        const storedPrefs = window.localStorage.getItem("color-theme") as
            | "light"
            | "dark"
            | null;
        if (storedPrefs) {
            return storedPrefs;
        }
    }
    return "light";
};

interface ThemeContextType {
    theme: "light" | "dark";
    setTheme: Dispatch<SetStateAction<"light" | "dark">>;
}

export const ThemeContext = React.createContext<ThemeContextType | undefined>(
    undefined,
);

export const ThemeProvider = ({ children }: { children: ReactNode }) => {
    const [theme, setTheme] = React.useState<"light" | "dark">(getInitialTheme);

    const rawSetTheme = (theme: "light" | "dark") => {
        const root = window.document.documentElement;
        const isDark = theme === "dark";

        root.classList.remove(isDark ? "light" : "dark");
        root.classList.add(theme);

        localStorage.setItem("color-theme", theme);
    };

    React.useEffect(() => {
        rawSetTheme(theme);
    }, [theme]);

    return (
        <ThemeContext.Provider value={{ theme, setTheme }}>
            {children}
        </ThemeContext.Provider>
    );
};

ThemeToggler.tsx

import { ReactElement } from "react";
import { useTheme } from "../../hooks/useTheme";
import { Sun, Moon } from "lucide-react";

function ThemeToggler(): ReactElement {
    const { theme, setTheme } = useTheme();

    function toggleTheme() {
        setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));
    }
    return theme === "light" ? (
        <Moon onClick={toggleTheme} />
    ) : (
        <Sun onClick={toggleTheme} />
    );
}

export default ThemeToggler;

useTheme.tsx

import { useContext } from "react";
import { ThemeContext } from "../Contexts/ThemeContext";

export const useTheme = () => {
    const context = useContext(ThemeContext);
    if (!context) {
        throw new Error("useTheme deve ser usado dentro de um ThemeProvider");
    }
    return context;
};

Header.tsx

import { ReactElement } from "react";
import ThemeToggler from "../ui/ThemeToggler";

function Header(): ReactElement {
    return (
        <header
            className={
                "flex h-20 w-svw items-center justify-between px-4 text-xl"
            }
        >
            <div>
                <h1>CashierApp</h1>
            </div>
            <div>
                <nav>
                    <ul className="flex flex-row items-center gap-8">
                        <li>Home</li>
                        <li>Controle de caixa</li>
                        <li>Cadastros</li>
                    </ul>
                </nav>
            </div>
            <div>
                <ThemeToggler />
            </div>
        </header>
    );
}

export default Header;

tailwind.config.ts

/** @type {import('tailwindcss').Config} */
export default {
    content: ["./index.html", "./src/**/*.{html,js,jsx,ts,tsx}"],
    theme: {
        extend: {
            colors: {
                primary: "var(--color-bg-primary)",
                secondary: "var(--color-bg-secondary)",
                textPrimary: "var(--color-text-primary)",
                textSecondary: "var(--color-text-secondary)",
                textAccent: "var(--color-text-accent)",
            },
        },
    },
    plugins: [],
};

Edit: I'm using tailwindcss v4, and my css file has the following statements:

@import "tailwindcss";

@tailwind utilities;


Solution

  • CSS-first configuration from TailwindCSS v4

    Since you're using v4, you don't need the tailwind.config.js file; instead, you should use the CSS-first directives.

    In CSS-first, you can define custom styles using the @theme directive.

    @import "tailwindcss";
    
    @theme {
      --font-display: "Satoshi", "sans-serif";
      --breakpoint-3xl: 120rem;
      --color-avocado-100: oklch(0.99 0 0);
      --color-avocado-200: oklch(0.98 0.04 113.22);
      --color-avocado-300: oklch(0.94 0.11 115.03);
      --color-avocado-400: oklch(0.92 0.19 114.08);
      --color-avocado-500: oklch(0.84 0.18 117.33);
      --color-avocado-600: oklch(0.53 0.12 118.34);
      --ease-fluid: cubic-bezier(0.3, 0, 0, 1);
      --ease-snappy: cubic-bezier(0.2, 0, 0, 1);
      /* ... */
    }
    

    Theme variables are defined in namespaces and each namespace corresponds to one or more utility class or variant APIs.

    How to use legacy JavaScript based configuration

    However, it is still possible to continue using the tailwind.config.js through the @config directive.

    Related: