Themer.tsx

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