@@ -2,39 +2,100 @@ import { useTheme } from 'next-themes';
2
2
import { useEffect , useState } from 'react' ;
3
3
import React from 'react' ;
4
4
5
- export default function DarkModeToggle ( ) {
6
- const { theme, setTheme } = useTheme ( ) ;
7
- const [ isDarkMode , setIsDarkMode ] = useState ( theme === 'dark' ) ;
8
- const [ isClickable , setIsClickable ] = useState ( true ) ;
9
- const [ img , setImg ] = useState ( '/icons/moon.svg' ) ;
10
-
11
- const toggleDarkMode = ( ) => {
12
- if ( ! isClickable ) return ;
13
-
14
- setIsClickable ( false ) ;
15
- const newTheme = isDarkMode ? 'light' : 'dark' ;
16
- setTheme ( newTheme ) ;
17
- setIsDarkMode ( ! isDarkMode ) ;
5
+ function ListItem ( {
6
+ children,
7
+ onClick,
8
+ } : {
9
+ children : React . ReactNode ;
10
+ onClick : ( ) => void ;
11
+ } ) {
12
+ return (
13
+ < div
14
+ onClick = { onClick }
15
+ className = 'p-2 hover:bg-gray-200 dark:hover:bg-gray-700 cursor-pointer rounded-md transition duration-150 flex row gap-2 w-full text-sm'
16
+ >
17
+ { children }
18
+ </ div >
19
+ ) ;
20
+ }
18
21
19
- setTimeout ( ( ) => {
20
- setIsClickable ( true ) ;
21
- } , 500 ) ;
22
- } ;
22
+ export default function DarkModeToggle ( ) {
23
+ const { theme, setTheme, resolvedTheme } = useTheme ( ) ;
24
+ const [ isDarkMode , setIsDarkMode ] = useState ( false ) ;
23
25
24
26
useEffect ( ( ) => {
25
- if ( ! theme ) setTheme ( 'light' ) ;
27
+ setIsDarkMode ( resolvedTheme === 'dark' ) ;
28
+ } , [ resolvedTheme ] ) ;
26
29
27
- const img = theme === 'dark' ? '/icons/sun.svg' : '/icons/moon.svg' ;
28
- setImg ( img ) ;
29
- } , [ theme , setTheme ] ) ;
30
+ const [ showSelect , setShowSelect ] = useState ( false ) ;
31
+ const [ activeThemeIcon , setActiveThemeIcon ] = useState ( '' ) ;
32
+ useEffect ( ( ) => {
33
+ switch ( theme ) {
34
+ case 'system' :
35
+ return setActiveThemeIcon ( '/icons/theme-switch.svg' ) ;
36
+ case 'light' :
37
+ return setActiveThemeIcon ( '/icons/sun.svg' ) ;
38
+ case 'dark' :
39
+ return setActiveThemeIcon ( '/icons/moon.svg' ) ;
40
+ }
41
+ } , [ theme , resolvedTheme ] ) ;
30
42
31
43
return (
32
- < button
33
- onClick = { toggleDarkMode }
34
- className = 'dark-mode-toggle rounded-md dark:hover:bg-gray-700 p-1.5 hover:bg-gray-100 focus:bg-gray-100 focus:outline-none transition duration-150'
35
- disabled = { ! isClickable }
36
- >
37
- < img src = { img } alt = 'Dark Mode' width = { 25 } height = { 25 } />
38
- </ button >
44
+ < div className = 'relative w-10 h-10 dark-mode-toggle-container' >
45
+ < button
46
+ onClick = { ( ) => setShowSelect ( ! showSelect ) }
47
+ className = 'dark-mode-toggle rounded-md dark:hover:bg-gray-700 p-1.5 hover:bg-gray-100 transition duration-150 '
48
+ >
49
+ < img
50
+ src = { activeThemeIcon }
51
+ alt = 'Dark Mode'
52
+ width = { 25 }
53
+ height = { 25 }
54
+ style = { {
55
+ // Invert the icon color based on the theme, theme of the light mode is dark
56
+ filter : isDarkMode ? 'invert(1)' : 'invert(0)' ,
57
+ } }
58
+ />
59
+ </ button >
60
+ < div
61
+ className = 'absolute right-0 p-2 bg-white dark:bg-gray-800 rounded-lg border dark:border-gray-700 z-10 w-max'
62
+ style = { { display : showSelect ? 'block' : 'none' } }
63
+ onMouseLeave = { ( ) => {
64
+ setShowSelect ( false ) ;
65
+ } }
66
+ tabIndex = { 0 }
67
+ >
68
+ < ListItem onClick = { ( ) => setTheme ( 'system' ) } >
69
+ < img
70
+ src = { '/icons/theme-switch.svg' }
71
+ alt = 'System theme'
72
+ width = { 18 }
73
+ height = { 18 }
74
+ style = { { filter : isDarkMode ? 'invert(1)' : 'invert(0)' } }
75
+ />
76
+ System
77
+ </ ListItem >
78
+ < ListItem onClick = { ( ) => setTheme ( 'light' ) } >
79
+ < img
80
+ src = { '/icons/sun.svg' }
81
+ alt = 'System theme'
82
+ width = { 18 }
83
+ height = { 18 }
84
+ style = { { filter : isDarkMode ? 'invert(1)' : 'invert(0)' } }
85
+ />
86
+ Light
87
+ </ ListItem >
88
+ < ListItem onClick = { ( ) => setTheme ( 'dark' ) } >
89
+ < img
90
+ src = { '/icons/moon.svg' }
91
+ alt = 'System theme'
92
+ width = { 18 }
93
+ height = { 18 }
94
+ style = { { filter : isDarkMode ? 'invert(1)' : 'invert(0)' } }
95
+ />
96
+ Dark
97
+ </ ListItem >
98
+ </ div >
99
+ </ div >
39
100
) ;
40
101
}
0 commit comments