From 6d96e7c06cdf97748609568f8b3c604ef6a84c13 Mon Sep 17 00:00:00 2001 From: yogeshkumawat2027 Date: Sat, 13 Dec 2025 18:23:19 +0530 Subject: [PATCH] Refactor: Replace dropdown theme menu with single-click toggle button for improved UX --- components/mode-toggle.tsx | 119 ++++++++++++++++++++++++++++--------- package-lock.json | 9 +-- 2 files changed, 97 insertions(+), 31 deletions(-) diff --git a/components/mode-toggle.tsx b/components/mode-toggle.tsx index 704bb69..14ba276 100644 --- a/components/mode-toggle.tsx +++ b/components/mode-toggle.tsx @@ -1,38 +1,103 @@ "use client"; -import { Moon, Sun } from "lucide-react"; +import { Moon, Sun, Monitor } from "lucide-react"; import { useTheme } from "next-themes"; +import { useEffect, useState } from "react"; import { Button } from "@/components/ui/button"; import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; export function ModeToggle() { - const { setTheme } = useTheme(); + const { theme, setTheme, resolvedTheme } = useTheme(); + const [mounted, setMounted] = useState(false); + + // Prevent hydration mismatch + useEffect(() => { + setMounted(true); + }, []); + + if (!mounted) { + return ( + + ); + } + + // Determine the next theme to cycle through + const nextTheme = () => { + if (theme === "light") { + setTheme("dark"); + } else if (theme === "dark") { + setTheme("system"); + } else { + setTheme("light"); + } + }; + + // Determine which icon to display based on resolved theme + const renderIcon = () => { + switch (resolvedTheme) { + case "dark": + return ( + + ); + case "light": + return ( + + ); + default: + return ( + + ); + } + }; + + // Determine tooltip text + const getTooltipText = () => { + switch (theme) { + case "light": + return "Light mode (click to switch to Dark)"; + case "dark": + return "Dark mode (click to switch to System)"; + case "system": + return `System theme - ${resolvedTheme === "dark" ? "Dark" : "Light"} (click to switch to Light)`; + default: + return "Toggle theme"; + } + }; + return ( - - - - - - setTheme("light")}> - Light - - setTheme("dark")}> - Dark - - setTheme("system")}> - System - - - + + + + + + + {getTooltipText()} + + + ); } diff --git a/package-lock.json b/package-lock.json index 0be1848..edb364b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4335,7 +4335,7 @@ "version": "19.1.6", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.6.tgz", "integrity": "sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==", - "devOptional": true, + "dev": true, "dependencies": { "csstype": "^3.0.2" } @@ -4344,7 +4344,7 @@ "version": "19.1.5", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.5.tgz", "integrity": "sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==", - "devOptional": true, + "dev": true, "peerDependencies": { "@types/react": "^19.0.0" } @@ -11018,7 +11018,8 @@ "node_modules/tailwindcss": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz", - "integrity": "sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==" + "integrity": "sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==", + "dev": true }, "node_modules/tailwindcss-animate": { "version": "1.0.7", @@ -11254,7 +11255,7 @@ "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "devOptional": true, + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver"