think/packages/client/src/hooks/use-theme.tsx

56 lines
1.2 KiB
TypeScript
Raw Normal View History

2022-05-12 03:10:56 +00:00
import { useCallback, useEffect, useState } from 'react';
2022-02-20 11:51:55 +00:00
2022-05-21 07:35:16 +00:00
import { createGlobalHook } from './create-global-hook';
export enum ThemeEnum {
2022-03-12 03:27:56 +00:00
'dark' = 'dark',
'light' = 'light',
2022-02-20 11:51:55 +00:00
}
2022-05-21 07:35:16 +00:00
const useThemeHook = () => {
const [theme, setTheme] = useState(ThemeEnum.light);
2022-02-20 11:51:55 +00:00
2022-05-12 03:10:56 +00:00
const toggle = useCallback(() => {
2022-05-21 07:35:16 +00:00
const nextTheme = theme === 'dark' ? ThemeEnum.light : ThemeEnum.dark;
2022-02-20 11:51:55 +00:00
setTheme(nextTheme);
2022-05-12 03:10:56 +00:00
}, [theme]);
2022-02-20 11:51:55 +00:00
useEffect(() => {
2022-03-23 10:08:07 +00:00
const body = document.body;
if (theme === 'dark') {
body.setAttribute('theme-mode', 'dark');
return;
}
if (theme === 'light') {
body.setAttribute('theme-mode', 'light');
return;
}
2022-02-20 11:51:55 +00:00
}, [theme]);
useEffect(() => {
2022-03-12 03:27:56 +00:00
const mql = window.matchMedia('(prefers-color-scheme: dark)');
2022-02-20 11:51:55 +00:00
function matchMode(e) {
if (e.matches) {
2022-05-21 07:35:16 +00:00
setTheme(ThemeEnum.dark);
2022-02-20 11:51:55 +00:00
} else {
2022-05-21 07:35:16 +00:00
setTheme(ThemeEnum.light);
2022-02-20 11:51:55 +00:00
}
}
matchMode(mql);
2022-03-12 03:27:56 +00:00
mql.addEventListener('change', matchMode);
2022-05-21 07:35:16 +00:00
return () => {
mql.removeEventListener('change', matchMode);
};
2022-02-20 11:51:55 +00:00
}, []);
return {
theme,
toggle,
};
};
2022-05-21 07:35:16 +00:00
export const Theme = createGlobalHook<{ theme: ThemeEnum; toggle: () => void }>(useThemeHook);