Skip to content

Instantly share code, notes, and snippets.

@ertugrulozcan
Created August 9, 2024 19:01
Show Gist options
  • Save ertugrulozcan/140cc7eae3cb8940543ce5d1917da544 to your computer and use it in GitHub Desktop.
Save ertugrulozcan/140cc7eae3cb8940543ce5d1917da544 to your computer and use it in GitHub Desktop.
import React, { useState, useEffect } from "react"
import { Dropdown, Button } from "antd"
import { ReduxStore } from "../../redux/ReduxStore"
import { useDispatch } from "react-redux"
import { changeDarkMode } from "../../redux/reducers/ThemeReducer"
import { MoonIcon, SunIcon, ComputerDesktopIcon } from '@heroicons/react/24/solid'
type ThemeSwitcherProps = {
className?: string
};
const ThemeSwitcher = (props: ThemeSwitcherProps) => {
const [theme, setTheme] = useState<'dark' | 'light' | 'system'>();
const dispatch = useDispatch();
ReduxStore.subscribe(() => {
setTheme(localStorage.appearance === 'dark' ? 'dark' : localStorage.appearance === 'system' ? 'system' : 'light')
})
useEffect(() => {
if (!theme) {
return;
}
const changeTheme = (isDark: boolean) => {
localStorage.appearance = theme;
localStorage.theme = isDark ? "dark" : "light";
if (isDark) {
document.documentElement.classList.add("dark");
}
else {
document.documentElement.classList.remove("dark");
}
dispatch(changeDarkMode(isDark ? "dark" : "light"));
}
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
changeTheme(theme === "dark" || (theme === "system" && mediaQuery.matches))
const handle = (e: MediaQueryListEvent) => {
changeTheme(theme === "dark" || (theme === "system" && e.matches))
}
mediaQuery.addEventListener("change", handle);
return () => {
mediaQuery.removeEventListener("change", handle);
}
}, [theme, dispatch]);
useEffect(() => {
setTheme(localStorage.appearance === 'dark' ? 'dark' : localStorage.appearance === 'system' ? 'system' : 'light')
}, [dispatch]);
const menuItems = [
{
key: 'light',
label: <span className="ml-1">{'Açık'}</span>,
icon: <SunIcon className="w-4 h-4 fill-orange-400" />,
disabled: theme === 'light',
className: "min-w-[8rem]",
onClick: () => { setTheme('light') }
},
{
key: 'dark',
label: <span className="ml-1">{'Koyu'}</span>,
icon: <MoonIcon className="w-4 h-4 fill-violet-600" />,
disabled: theme === 'dark',
className: "min-w-[8rem]",
onClick: () => { setTheme('dark') }
},
{
key: 'system',
label: <span className="ml-1">{'Sistem'}</span>,
icon: <ComputerDesktopIcon className="w-4 h-4 fill-sky-600" />,
disabled: theme === 'system',
className: "min-w-[8rem]",
onClick: () => { setTheme('system') }
}
]
const isDark = theme === "dark" || (theme === "system" && window.matchMedia('(prefers-color-scheme: dark)').matches)
return (
<Dropdown menu={{ items: menuItems, selectable: true, defaultSelectedKeys: theme ? [theme] : [], className: "min-w-[10rem]" }} trigger={["click"]} placement="bottomLeft" arrow={true} className={props.className || ""} rootClassName="theme-switcher">
<Button type="text" style={{ paddingInline: "8px" }}>
{isDark ? <MoonIcon className="w-4 h-4 fill-violet-600" /> : <SunIcon className="w-4 h-4 fill-orange-400" />}
</Button>
</Dropdown>
)
};
export default ThemeSwitcher;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment