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 description = `Switch to ${mode === 'light' ? 'dark' : 'light'} theme`;
17
18  return (
19    <Tooltip title={description}>
20      <IconButton onClick={toggleMode} aria-label={description}>
21        {mode === 'light' ? (
22          <WbSunnyRounded color="secondary" />
23        ) : (
24          <NightsStayRounded color="secondary" />
25        )}
26      </IconButton>
27    </Tooltip>
28  );
29};
30
31type Props = {
32  children: React.ReactNode;
33  lightTheme: Theme;
34  darkTheme: Theme;
35};
36const Themer = ({ children, lightTheme, darkTheme }: Props) => {
37  const preferseDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
38  const browserMode = preferseDarkMode ? 'dark' : 'light';
39  const savedMode = localStorage.getItem('themeMode');
40  const preferedMode = savedMode != null ? savedMode : browserMode;
41  const [curMode, setMode] = useState(preferedMode);
42
43  const toggleMode = () => {
44    const preferedMode = curMode === 'light' ? 'dark' : 'light';
45    localStorage.setItem('themeMode', preferedMode);
46    setMode(preferedMode);
47  };
48
49  const preferedTheme = preferedMode === 'dark' ? darkTheme : lightTheme;
50
51  return (
52    <ThemeContext.Provider value={{ toggleMode: toggleMode, mode: curMode }}>
53      <ThemeProvider theme={preferedTheme}>{children}</ThemeProvider>
54    </ThemeContext.Provider>
55  );
56};
57
58export { Themer as default, LightSwitch };