Themer.tsx

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