theme-switch.tsx 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import { useEffect } from 'react'
  2. import { IconCheck, IconMoon, IconSun } from '@tabler/icons-react'
  3. import { cn } from '@/lib/utils'
  4. import { useTheme } from '@/context/theme-context'
  5. import { Button } from '@/components/ui/button'
  6. import {
  7. DropdownMenu,
  8. DropdownMenuContent,
  9. DropdownMenuItem,
  10. DropdownMenuTrigger,
  11. } from '@/components/ui/dropdown-menu'
  12. export function ThemeSwitch() {
  13. const { theme, setTheme } = useTheme()
  14. /* Update theme-color meta tag
  15. * when theme is updated */
  16. useEffect(() => {
  17. const themeColor = theme === 'dark' ? '#020817' : '#fff'
  18. const metaThemeColor = document.querySelector("meta[name='theme-color']")
  19. if (metaThemeColor) metaThemeColor.setAttribute('content', themeColor)
  20. }, [theme])
  21. return (
  22. <DropdownMenu modal={false}>
  23. <DropdownMenuTrigger asChild>
  24. <Button variant='ghost' size='icon' className='scale-95 rounded-full'>
  25. <IconSun className='size-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0' />
  26. <IconMoon className='absolute size-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100' />
  27. <span className='sr-only'>Toggle theme</span>
  28. </Button>
  29. </DropdownMenuTrigger>
  30. <DropdownMenuContent align='end'>
  31. <DropdownMenuItem onClick={() => setTheme('light')}>
  32. Light{' '}
  33. <IconCheck
  34. size={14}
  35. className={cn('ml-auto', theme !== 'light' && 'hidden')}
  36. />
  37. </DropdownMenuItem>
  38. <DropdownMenuItem onClick={() => setTheme('dark')}>
  39. Dark
  40. <IconCheck
  41. size={14}
  42. className={cn('ml-auto', theme !== 'dark' && 'hidden')}
  43. />
  44. </DropdownMenuItem>
  45. <DropdownMenuItem onClick={() => setTheme('system')}>
  46. System
  47. <IconCheck
  48. size={14}
  49. className={cn('ml-auto', theme !== 'system' && 'hidden')}
  50. />
  51. </DropdownMenuItem>
  52. </DropdownMenuContent>
  53. </DropdownMenu>
  54. )
  55. }