Themer.tsx

 1import React, { createContext, useContext, useState } from 'react';
 2
 3import { ThemeProvider, useMediaQuery } from '@material-ui/core';
 4import IconButton from '@material-ui/core/IconButton/IconButton';
 5import Tooltip from '@material-ui/core/Tooltip/Tooltip';
 6import { Theme } from '@material-ui/core/styles';
 7import { NightsStayRounded, WbSunnyRounded } from '@material-ui/icons';
 8
 9const ThemeContext = createContext({
10  toggleMode: () => {},
11  mode: '',
12});
13
14const LightSwitch = () => {
15  const { mode, toggleMode } = useContext(ThemeContext);
16  const nextMode = mode === 'light' ? 'dark' : 'light';
17  const description = `Switch to ${nextMode} theme`;
18
19  return (
20    <Tooltip title={description}>
21      <IconButton onClick={toggleMode} aria-label={description}>
22        {mode === 'light' ? (
23          <WbSunnyRounded color="secondary" />
24        ) : (
25          <NightsStayRounded color="secondary" />
26        )}
27      </IconButton>
28    </Tooltip>
29  );
30};
31
32type Props = {
33  children: React.ReactNode;
34  lightTheme: Theme;
35  darkTheme: Theme;
36};
37const Themer = ({ children, lightTheme, darkTheme }: Props) => {
38  const preferseDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
39  const browserMode = preferseDarkMode ? 'dark' : 'light';
40  const savedMode = localStorage.getItem('themeMode');
41  const preferedMode = savedMode != null ? savedMode : browserMode;
42  const [curMode, setMode] = useState(preferedMode);
43
44  const toggleMode = () => {
45    const preferedMode = curMode === 'light' ? 'dark' : 'light';
46    localStorage.setItem('themeMode', preferedMode);
47    setMode(preferedMode);
48  };
49
50  const preferedTheme = preferedMode === 'dark' ? darkTheme : lightTheme;
51
52  return (
53    <ThemeContext.Provider value={{ toggleMode: toggleMode, mode: curMode }}>
54      <ThemeProvider theme={preferedTheme}>{children}</ThemeProvider>
55    </ThemeContext.Provider>
56  );
57};
58
59export { Themer as default, LightSwitch };