|
| 1 | +import ThemeCustomizer from '@/components/theme-customizer'; |
1 | 2 | import { Button } from '@/components/ui/button'; |
2 | 3 | import { |
3 | 4 | DropdownMenu, |
4 | 5 | DropdownMenuContent, |
5 | | - DropdownMenuItem, |
6 | 6 | DropdownMenuTrigger, |
7 | 7 | } from '@/components/ui/dropdown-menu'; |
8 | 8 | import { useAppearance } from '@/hooks/use-appearance'; |
9 | | -import { Monitor, Moon, Sun } from 'lucide-react'; |
| 9 | +import { Moon, Palette, Sun } from 'lucide-react'; |
10 | 10 | import { HTMLAttributes } from 'react'; |
11 | 11 |
|
12 | | -export default function AppearanceToggleDropdown({ |
| 12 | +export default function AppearanceDropdown({ |
13 | 13 | className = '', |
14 | 14 | ...props |
15 | 15 | }: HTMLAttributes<HTMLDivElement>) { |
16 | 16 | const { appearance, updateAppearance } = useAppearance(); |
17 | 17 |
|
18 | | - const getCurrentIcon = () => { |
19 | | - switch (appearance) { |
20 | | - case 'dark': |
21 | | - return <Moon className="h-5 w-5" />; |
22 | | - case 'light': |
23 | | - return <Sun className="h-5 w-5" />; |
24 | | - default: |
25 | | - return <Monitor className="h-5 w-5" />; |
26 | | - } |
| 18 | + const isDark = |
| 19 | + appearance === 'dark' || |
| 20 | + (typeof window !== 'undefined' && |
| 21 | + appearance === 'system' && |
| 22 | + window.matchMedia && |
| 23 | + window.matchMedia('(prefers-color-scheme: dark)').matches); |
| 24 | + |
| 25 | + const handleQuickToggle = (e?: React.MouseEvent) => { |
| 26 | + // Prevent the trigger from closing/opening the dropdown when toggling |
| 27 | + e?.stopPropagation(); |
| 28 | + const newAppearance = isDark ? 'light' : 'dark'; |
| 29 | + updateAppearance(newAppearance); |
27 | 30 | }; |
28 | 31 |
|
29 | 32 | return ( |
30 | | - <div className={className} {...props}> |
| 33 | + <div className={`flex items-center space-x-1 ${className}`} {...props}> |
| 34 | + {/* Quick toggle button */} |
| 35 | + <Button |
| 36 | + variant="ghost" |
| 37 | + size="icon" |
| 38 | + className="h-9 w-9 rounded-md" |
| 39 | + onClick={handleQuickToggle} |
| 40 | + aria-label={ |
| 41 | + isDark ? 'Switch to light theme' : 'Switch to dark theme' |
| 42 | + } |
| 43 | + > |
| 44 | + {isDark ? ( |
| 45 | + <Moon className="h-5 w-5" /> |
| 46 | + ) : ( |
| 47 | + <Sun className="h-5 w-5" /> |
| 48 | + )} |
| 49 | + </Button> |
| 50 | + |
| 51 | + {/* Separate chevron trigger to open the customizer dropdown */} |
31 | 52 | <DropdownMenu> |
32 | 53 | <DropdownMenuTrigger asChild> |
33 | 54 | <Button |
34 | 55 | variant="ghost" |
35 | 56 | size="icon" |
36 | | - className="h-9 w-9 rounded-md" |
| 57 | + className="h-8 w-8 rounded-md p-1" |
| 58 | + aria-label="Open theme customizer" |
37 | 59 | > |
38 | | - {getCurrentIcon()} |
39 | | - <span className="sr-only">Toggle theme</span> |
| 60 | + <Palette className="h-4 w-4" /> |
40 | 61 | </Button> |
41 | 62 | </DropdownMenuTrigger> |
42 | | - <DropdownMenuContent align="end"> |
43 | | - <DropdownMenuItem onClick={() => updateAppearance('light')}> |
44 | | - <span className="flex items-center gap-2"> |
45 | | - <Sun className="h-5 w-5" /> |
46 | | - Light |
47 | | - </span> |
48 | | - </DropdownMenuItem> |
49 | | - <DropdownMenuItem onClick={() => updateAppearance('dark')}> |
50 | | - <span className="flex items-center gap-2"> |
51 | | - <Moon className="h-5 w-5" /> |
52 | | - Dark |
53 | | - </span> |
54 | | - </DropdownMenuItem> |
55 | | - <DropdownMenuItem |
56 | | - onClick={() => updateAppearance('system')} |
57 | | - > |
58 | | - <span className="flex items-center gap-2"> |
59 | | - <Monitor className="h-5 w-5" /> |
60 | | - System |
61 | | - </span> |
62 | | - </DropdownMenuItem> |
| 63 | + |
| 64 | + <DropdownMenuContent align="end" className="w-80"> |
| 65 | + <div className="p-4"> |
| 66 | + <h3 className="mb-2 text-sm font-semibold"> |
| 67 | + Customize theme |
| 68 | + </h3> |
| 69 | + <ThemeCustomizer /> |
| 70 | + </div> |
63 | 71 | </DropdownMenuContent> |
64 | 72 | </DropdownMenu> |
65 | 73 | </div> |
|
0 commit comments