From 51b871f636e3c4cdce23f6a612432e190e1aa3ef Mon Sep 17 00:00:00 2001 From: macbook Date: Tue, 26 May 2026 22:26:39 +0100 Subject: [PATCH] dark mode --- src/app/globals.css | 2 + src/app/layout.tsx | 8 +++- src/app/page.tsx | 2 - src/app/referral/leaderboard/page.tsx | 2 +- src/app/referral/page.tsx | 2 +- src/components/ClientProviders.tsx | 41 ++++++++++-------- src/components/GlobalThemeToggle.tsx | 14 +++++++ src/components/ThemeProvider.tsx | 22 ++++++++++ src/components/ThemeSwitcher.tsx | 60 ++++++++++++--------------- 9 files changed, 96 insertions(+), 57 deletions(-) create mode 100644 src/components/GlobalThemeToggle.tsx create mode 100644 src/components/ThemeProvider.tsx diff --git a/src/app/globals.css b/src/app/globals.css index 9cd8b104..f7f81d85 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -101,6 +101,7 @@ body { } :root { + color-scheme: light; --radius: 0.625rem; --background: oklch(1 0 0); --foreground: oklch(0.145 0 0); @@ -137,6 +138,7 @@ body { } .dark { + color-scheme: dark; --background: oklch(0.145 0 0); --foreground: oklch(0.985 0 0); --card: oklch(0.205 0 0); diff --git a/src/app/layout.tsx b/src/app/layout.tsx index da9505c4..e4ffa4e8 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -34,9 +34,13 @@ export default async function RootLayout({ const isRTL = ["ar", "he"].includes(preferredLang); return ( - + {children} diff --git a/src/app/page.tsx b/src/app/page.tsx index f324170d..97b47621 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -11,7 +11,6 @@ import { ErrorCategory, ErrorSeverity } from "@/types/errors"; import { logger } from "@/utils/logger"; import { WalletConnector } from "@/components/WalletConnector"; import { LanguageSwitcher } from "@/components/LanguageSwitcher"; -import { ThemeSwitcher } from "@/components/ThemeSwitcher"; import { ChainAware, ChainSpecific, @@ -118,7 +117,6 @@ function HomeContent() {
-
diff --git a/src/app/referral/leaderboard/page.tsx b/src/app/referral/leaderboard/page.tsx index 1b1ddf7d..66f4ada8 100644 --- a/src/app/referral/leaderboard/page.tsx +++ b/src/app/referral/leaderboard/page.tsx @@ -12,7 +12,7 @@ export const metadata = { export default function LeaderboardPage() { return ( -
+
diff --git a/src/app/referral/page.tsx b/src/app/referral/page.tsx index 55a0c73b..27cd6388 100644 --- a/src/app/referral/page.tsx +++ b/src/app/referral/page.tsx @@ -12,7 +12,7 @@ export const metadata = { export default function ReferralPage() { return ( -
+
diff --git a/src/components/ClientProviders.tsx b/src/components/ClientProviders.tsx index 49a18b0d..454d6b20 100644 --- a/src/components/ClientProviders.tsx +++ b/src/components/ClientProviders.tsx @@ -14,6 +14,8 @@ import dynamic from "next/dynamic"; import { useOnboardingStore } from "@/store/onboardingStore"; import { DomainWarningBanner } from "@/components/DomainWarningBanner"; import { useEffect } from "react"; +import { ThemeProvider } from "@/components/ThemeProvider"; +import { GlobalThemeToggle } from "@/components/GlobalThemeToggle"; interface ClientProvidersProps { children: React.ReactNode; @@ -59,23 +61,26 @@ export function ClientProviders({ children }: ClientProvidersProps) { }, [hasCompletedOnboarding, startOnboarding]); return ( - - - - - - - - - {children} - - - - - - - - - + + + + + + + + + + {children} + + + + + + + + + + + ); } diff --git a/src/components/GlobalThemeToggle.tsx b/src/components/GlobalThemeToggle.tsx new file mode 100644 index 00000000..742eb60d --- /dev/null +++ b/src/components/GlobalThemeToggle.tsx @@ -0,0 +1,14 @@ +"use client"; + +import { ThemeSwitcher } from "@/components/ThemeSwitcher"; + +export function GlobalThemeToggle() { + return ( +
+ +
+ ); +} diff --git a/src/components/ThemeProvider.tsx b/src/components/ThemeProvider.tsx new file mode 100644 index 00000000..aadbf72b --- /dev/null +++ b/src/components/ThemeProvider.tsx @@ -0,0 +1,22 @@ +"use client"; + +import * as React from "react"; +import { ThemeProvider as NextThemesProvider } from "next-themes"; + +interface ThemeProviderProps { + children: React.ReactNode; +} + +export function ThemeProvider({ children }: ThemeProviderProps) { + return ( + + {children} + + ); +} diff --git a/src/components/ThemeSwitcher.tsx b/src/components/ThemeSwitcher.tsx index 2a72d3e4..832b6f78 100644 --- a/src/components/ThemeSwitcher.tsx +++ b/src/components/ThemeSwitcher.tsx @@ -1,57 +1,51 @@ "use client"; -import { useEffect, useState } from 'react'; -import { Button } from '@/components/ui/button'; -import { Moon, Sun } from 'lucide-react'; +import { useEffect, useState } from "react"; +import { Moon, Sun } from "lucide-react"; +import { useTheme } from "next-themes"; -export function ThemeSwitcher() { - const [isDark, setIsDark] = useState(false); +import { Button } from "@/components/ui/button"; +import { cn } from "@/lib/utils"; + +interface ThemeSwitcherProps { + className?: string; + size?: "sm" | "default" | "icon"; +} + +export function ThemeSwitcher({ + className, + size = "sm", +}: ThemeSwitcherProps) { const [isMounted, setIsMounted] = useState(false); + const { resolvedTheme, setTheme } = useTheme(); useEffect(() => { setIsMounted(true); - const saved = localStorage.getItem('theme'); - const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; - const isDarkMode = saved === 'dark' || (saved === null && prefersDark); - - setIsDark(isDarkMode); - if (isDarkMode) { - document.documentElement.classList.add('dark'); - } else { - document.documentElement.classList.remove('dark'); - } }, []); const toggleTheme = () => { - const newIsDark = !isDark; - setIsDark(newIsDark); - - if (newIsDark) { - document.documentElement.classList.add('dark'); - localStorage.setItem('theme', 'dark'); - } else { - document.documentElement.classList.remove('dark'); - localStorage.setItem('theme', 'light'); - } + setTheme(resolvedTheme === "dark" ? "light" : "dark"); }; if (!isMounted) { - return
; + const placeholderSize = size === "icon" ? "h-11 w-11" : "h-8 w-20"; + return
; } + const isDark = resolvedTheme === "dark"; + return ( ); }