Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 1x 1x 10x 10x 10x 10x 5x 5x 2x 2x 2x 5x 3x 3x 3x 3x 10x 10x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 10x 10x 10x 10x 10x 10x 10x 4x 4x 4x 4x 4x 4x 4x 6x 6x 6x 10x 10x 1x | import React, { useEffect, useState } from "react"; interface ThemeToggleProps { testId?: string; } /** * Component for toggling between light and dark themes * * ## Business Perspective * Improves user experience by allowing customization of the interface * based on personal preference and environmental conditions. 🎨 */ const ThemeToggle: React.FC<ThemeToggleProps> = ({ testId = "theme-toggle", }) => { const [darkMode, setDarkMode] = useState<boolean>(false); // Initialize theme from localStorage or system preference useEffect(() => { const savedTheme = localStorage.getItem("theme"); if (savedTheme === "dark") { setDarkMode(true); document.documentElement.classList.remove("light"); document.documentElement.classList.add("dark"); } else if (savedTheme === "light" || !savedTheme) { setDarkMode(false); document.documentElement.classList.remove("dark"); document.documentElement.classList.add("light"); } else { // Check system preference const prefersDark = window.matchMedia( "(prefers-color-scheme: dark)" ).matches; setDarkMode(prefersDark); if (prefersDark) { document.documentElement.classList.remove("light"); document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); document.documentElement.classList.add("light"); } } }, []); const toggleTheme = () => { setDarkMode((prev) => { const newDarkMode = !prev; // Handle class changes synchronously for testing if (newDarkMode) { // To dark mode document.documentElement.classList.remove("light"); document.documentElement.classList.add("dark"); localStorage.setItem("theme", "dark"); } else { // To light mode - ensure we set light class properly document.documentElement.classList.remove("dark"); document.documentElement.classList.add("light"); localStorage.setItem("theme", "light"); } return newDarkMode; }); }; return ( <button data-testid={testId} onClick={toggleTheme} className="p-2 rounded-md text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-white focus:outline-none focus:ring-2 focus:ring-primary-500" aria-label={darkMode ? "Switch to light theme" : "Switch to dark theme"} > {darkMode ? ( <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"> <path fillRule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" clipRule="evenodd" /> </svg> ) : ( <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"> <path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" /> </svg> )} </button> ); }; export default ThemeToggle; |