jonbio/components/ThemeSwitch.tsx
Alejandro Sánchez Yalí 56a08dadf6 fix: resolve console error when switching between light and dark modes
This commit addresses the issue where an error was logged in the console when the user switched between light and dark modes. The warning was caused by the inappropriate use of SVG tags in JSX. The solution involved correcting the SVG tag usage to comply with JSX syntax requirements.

Closes #974
2024-07-18 20:44:23 -05:00

134 lines
4.9 KiB
TypeScript

'use client'
import { Fragment, useEffect, useState } from 'react'
import { useTheme } from 'next-themes'
import { Menu, RadioGroup, Transition } from '@headlessui/react'
const Sun = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
className="group:hover:text-gray-100 h-6 w-6"
>
<path
fillRule="evenodd"
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
clipRule="evenodd"
/>
</svg>
)
const Moon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
className="group:hover:text-gray-100 h-6 w-6"
>
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
</svg>
)
const Monitor = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="group:hover:text-gray-100 h-6 w-6"
>
<rect x="3" y="3" width="14" height="10" rx="2" ry="2"></rect>
<line x1="7" y1="17" x2="13" y2="17"></line>
<line x1="10" y1="13" x2="10" y2="17"></line>
</svg>
)
const Blank = () => <svg className="h-6 w-6" />
const ThemeSwitch = () => {
const [mounted, setMounted] = useState(false)
const { theme, setTheme, resolvedTheme } = useTheme()
// When mounted on client, now we can show the UI
useEffect(() => setMounted(true), [])
return (
<div className="mr-5 flex items-center">
<Menu as="div" className="relative inline-block text-left">
<div className="flex items-center justify-center hover:text-primary-500 dark:hover:text-primary-400">
<Menu.Button>
{mounted ? resolvedTheme === 'dark' ? <Moon /> : <Sun /> : <Blank />}
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 z-50 mt-2 w-32 origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-gray-800">
<RadioGroup value={theme} onChange={setTheme}>
<div className="p-1">
<RadioGroup.Option value="light">
<Menu.Item>
{({ active }) => (
<button
className={`${
active ? 'bg-primary-600 text-white' : ''
} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
>
<div className="mr-2">
<Sun />
</div>
Light
</button>
)}
</Menu.Item>
</RadioGroup.Option>
<RadioGroup.Option value="dark">
<Menu.Item>
{({ active }) => (
<button
className={`${
active ? 'bg-primary-600 text-white' : ''
} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
>
<div className="mr-2">
<Moon />
</div>
Dark
</button>
)}
</Menu.Item>
</RadioGroup.Option>
<RadioGroup.Option value="system">
<Menu.Item>
{({ active }) => (
<button
className={`${
active ? 'bg-primary-600 text-white' : ''
} group flex w-full items-center rounded-md px-2 py-2 text-sm`}
>
<div className="mr-2">
<Monitor />
</div>
System
</button>
)}
</Menu.Item>
</RadioGroup.Option>
</div>
</RadioGroup>
</Menu.Items>
</Transition>
</Menu>
</div>
)
}
export default ThemeSwitch