From 301b84535535788c8f2bcb3dfc657daffdd5ec9d Mon Sep 17 00:00:00 2001 From: idiottrader <429136075@qq.com> Date: Sat, 28 Feb 2026 22:38:57 +0800 Subject: [PATCH 1/7] feat: add ThemeProvider for dark mode support --- src/components/ThemeProvider.tsx | 64 ++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/components/ThemeProvider.tsx diff --git a/src/components/ThemeProvider.tsx b/src/components/ThemeProvider.tsx new file mode 100644 index 0000000..982e80c --- /dev/null +++ b/src/components/ThemeProvider.tsx @@ -0,0 +1,64 @@ +"use client"; + +import React, { createContext, useContext, useState, useEffect } from "react"; + +type Theme = "light" | "dark"; + +interface ThemeContextType { + theme: Theme; + toggleTheme: () => void; + setTheme: (theme: Theme) => void; +} + +const ThemeContext = createContext(undefined); + +export function useTheme() { + const context = useContext(ThemeContext); + if (context === undefined) { + throw new Error("useTheme must be used within a ThemeProvider"); + } + return context; +} + +export function ThemeProvider({ children }: { children: React.ReactNode }) { + const [theme, setThemeState] = useState("light"); + const [mounted, setMounted] = useState(false); + + useEffect(() => { + setMounted(true); + // Check localStorage for saved theme preference + const savedTheme = localStorage.getItem("theme") as Theme | null; + if (savedTheme) { + setThemeState(savedTheme); + document.documentElement.classList.toggle("dark", savedTheme === "dark"); + } else { + // Check system preference + const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches; + const initialTheme = prefersDark ? "dark" : "light"; + setThemeState(initialTheme); + document.documentElement.classList.toggle("dark", prefersDark); + } + }, []); + + const setTheme = (newTheme: Theme) => { + setThemeState(newTheme); + localStorage.setItem("theme", newTheme); + document.documentElement.classList.toggle("dark", newTheme === "dark"); + }; + + const toggleTheme = () => { + const newTheme = theme === "light" ? "dark" : "light"; + setTheme(newTheme); + }; + + // Prevent hydration mismatch by not rendering until mounted + if (!mounted) { + return <>{children}; + } + + return ( + + {children} + + ); +} From f2d86fb88acbc467318ebd6ee6338e41ba6da54c Mon Sep 17 00:00:00 2001 From: idiottrader <429136075@qq.com> Date: Sat, 28 Feb 2026 22:39:07 +0800 Subject: [PATCH 2/7] feat: add ThemeToggle component --- src/components/ThemeToggle.tsx | 49 ++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/components/ThemeToggle.tsx diff --git a/src/components/ThemeToggle.tsx b/src/components/ThemeToggle.tsx new file mode 100644 index 0000000..428475a --- /dev/null +++ b/src/components/ThemeToggle.tsx @@ -0,0 +1,49 @@ +"use client"; + +import { useTheme } from "./ThemeProvider"; + +export function ThemeToggle() { + const { theme, toggleTheme } = useTheme(); + + return ( + + ); +} From aad0d4210324bfa3c07820993715de172cd0c9b4 Mon Sep 17 00:00:00 2001 From: idiottrader <429136075@qq.com> Date: Sat, 28 Feb 2026 22:39:27 +0800 Subject: [PATCH 3/7] feat: add ThemeToggle to Navbar with dark mode styles --- src/components/Navbar.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 2d673aa..907450a 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -2,32 +2,36 @@ import Link from "next/link"; import { ConnectWallet } from "./ConnectWallet"; +import { ThemeToggle } from "./ThemeToggle"; export function Navbar() { return ( -