Themer.tsx

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