1+ import { useState , useRef , useEffect } from 'react' ;
2+ import { useTheme } from '@/shared/theme/useTheme' ;
3+ import { SunIcon , MoonIcon } from '@heroicons/react/24/outline' ;
4+ import type { ThemeName } from './shared/theme' ;
5+
6+ function ThemeToggleSwitch ( ) {
7+ const { themeName, setTheme } = useTheme ( ) ;
8+ const [ open , setOpen ] = useState ( false ) ;
9+ const ref = useRef < HTMLDivElement > ( null ) ;
10+
11+ // Close dropdown on outside click
12+ useEffect ( ( ) => {
13+ const handleClickOutside = ( e : MouseEvent ) => {
14+ if ( ref . current && ! ref . current . contains ( e . target as Node ) ) {
15+ setOpen ( false ) ;
16+ }
17+ } ;
18+ document . addEventListener ( 'mousedown' , handleClickOutside ) ;
19+ return ( ) => document . removeEventListener ( 'mousedown' , handleClickOutside ) ;
20+ } , [ ] ) ;
21+
22+ const handleSelect = ( theme : string ) => {
23+ if ( theme === 'digital' || theme === 'monochrome' ) return ; // placeholder
24+ setTheme ( theme as ThemeName ) ;
25+ setOpen ( false ) ;
26+ } ;
27+
28+ return (
29+ < div className = "relative inline-block absolute top-4 left-4" ref = { ref } >
30+ { /* Toggle Button */ }
31+ < button
32+ onClick = { ( ) => setOpen ( ( prev ) => ! prev ) }
33+ className = "cursor-pointer flex items-center justify-center w-9 h-9 rounded-md
34+ bg-bg-secondary border border-border-secondary
35+ text-text-secondary hover:bg-bg-tertiary
36+ transition"
37+ >
38+ { themeName === 'dark' ?
39+ < MoonIcon className = "size-6" />
40+ :
41+ < SunIcon className = "size-6" />
42+ }
43+ </ button >
44+
45+ { /* Dropdown */ }
46+ { open && (
47+ < div
48+ className = "absolute right-0 mt-2 w-44 rounded-lg
49+ bg-bg-secondary border border-border-primary
50+ shadow-md p-1 space-y-1 z-50"
51+ >
52+ { /* Light */ }
53+ < button
54+ onClick = { ( ) => handleSelect ( 'light' ) }
55+ className = "cursor-pointer w-full text-left px-3 py-2 rounded-md text-sm
56+ text-text-primary hover:bg-bg-tertiary transition"
57+ >
58+ Light
59+ </ button >
60+
61+ { /* Dark */ }
62+ < button
63+ onClick = { ( ) => handleSelect ( 'dark' ) }
64+ className = "cursor-pointer w-full text-left px-3 py-2 rounded-md text-sm
65+ text-text-primary hover:bg-bg-tertiary transition"
66+ >
67+ Dark
68+ </ button >
69+
70+ { /* Divider */ }
71+ < div className = "h-px bg-border-tertiary my-1" />
72+
73+ { /* Digital (disabled) */ }
74+ < button
75+ disabled
76+ className = "cursor-pointer w-full text-left px-3 py-2 rounded-md text-sm
77+ text-text-tertiary cursor-not-allowed"
78+ >
79+ Digital (coming soon)
80+ </ button >
81+
82+ { /* Monochrome (disabled) */ }
83+ < button
84+ disabled
85+ className = "cursor-pointer w-full text-left px-3 py-2 rounded-md text-sm
86+ text-text-tertiary cursor-not-allowed"
87+ >
88+ Monochrome (coming soon)
89+ </ button >
90+ </ div >
91+ ) }
92+ </ div >
93+ ) ;
94+ }
95+
96+ export default ThemeToggleSwitch ;
0 commit comments