ThemeToggle.tsx80 lines · main
1'use client'
2
3import { Moon, Sun } from 'lucide-react'
4import { useTheme } from 'next-themes'
5import { useEffect, useState } from 'react'
6import {
7 cn,
8 DropdownMenu,
9 DropdownMenuContent,
10 DropdownMenuGroup,
11 DropdownMenuRadioGroup,
12 DropdownMenuRadioItem,
13 DropdownMenuTrigger,
14 Theme,
15 themes,
16} from 'ui'
17
18interface ThemeToggleProps {
19 forceDark?: boolean
20 triggerClassName?: string
21 contentClassName?: string
22}
23
24export const ThemeToggle = ({
25 forceDark = false,
26 triggerClassName,
27 contentClassName,
28}: ThemeToggleProps) => {
29 const { theme, setTheme, resolvedTheme } = useTheme()
30 const [open, setOpen] = useState(false)
31 const [isMounted, setIsMounted] = useState(false)
32
33 useEffect(() => {
34 setIsMounted(true)
35 }, [])
36
37 // Conditionally force the theme to 'dark' when disabled is true
38 const currentTheme = forceDark ? 'dark' : theme
39
40 if (!isMounted) return null
41
42 return (
43 <DropdownMenu open={open} onOpenChange={() => setOpen(!open)} modal={false}>
44 <DropdownMenuTrigger asChild disabled={forceDark}>
45 <button
46 id="user-settings-dropdown"
47 className={cn(
48 'flex items-center justify-center h-7 w-7 text-foreground-light',
49 triggerClassName
50 )}
51 >
52 {resolvedTheme === 'dark' ? (
53 <Moon className="h-[20px] w-[20px] rotate-90 transition-all dark:rotate-0" />
54 ) : (
55 <Sun className="w-[20px] h-[20px] rotate-0 transition-all dark:-rotate-90" />
56 )}
57 <span className="sr-only">Toggle theme</span>
58 </button>
59 </DropdownMenuTrigger>
60 <DropdownMenuContent align="end" className={cn('w-60', contentClassName)}>
61 <DropdownMenuGroup>
62 <DropdownMenuRadioGroup
63 value={currentTheme} // Use the currentTheme variable here
64 onValueChange={(value) => {
65 setTheme(value)
66 }}
67 >
68 {themes
69 .filter((x) => x.value === 'dark' || x.value === 'light' || x.value === 'system')
70 .map((theme: Theme) => (
71 <DropdownMenuRadioItem key={theme.value} value={theme.value}>
72 {theme.name}
73 </DropdownMenuRadioItem>
74 ))}
75 </DropdownMenuRadioGroup>
76 </DropdownMenuGroup>
77 </DropdownMenuContent>
78 </DropdownMenu>
79 )
80}