import { useMediaQuery } from '@mui/material'; import { createTheme, StyledEngineProvider } from '@mui/material/styles'; import ThemeProvider from '@mui/material/styles/ThemeProvider'; import React, { createContext, ReactNode, useContext, useEffect, useState, } from 'react'; export type ThemeMode = 'dark' | 'light'; type ThemeModeState = { themeMode: ThemeMode; setThemeMode: React.Dispatch>; }; export const ThemeModeContext = createContext(null); type ThemeModeContextProviderProps = { children: ReactNode; }; export function ThemeContextProvider({ children, }: ThemeModeContextProviderProps) { const rootElement = document.getElementById('root'); const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); const [themeMode, setThemeMode] = useState(() => { const manualThemeMode = localStorage.getItem('themeMode') as ThemeMode; if (manualThemeMode) { return manualThemeMode; } return prefersDarkMode ? 'dark' : 'light'; }); useEffect(() => { localStorage.setItem('themeMode', themeMode as ThemeMode); }, [themeMode]); const muiTheme = createTheme({ palette: { mode: themeMode, }, // All `Portal`-related components need to have the the main app wrapper element as a container // so that they are in the subtree under the element used in the `important` option of the Tailwind's config. components: { MuiPopover: { defaultProps: { container: rootElement, }, }, MuiPopper: { defaultProps: { container: rootElement, }, }, MuiDialog: { defaultProps: { container: rootElement, }, }, MuiModal: { defaultProps: { container: rootElement, }, }, }, }); return ( {children} ); } // eslint-disable-next-line react-refresh/only-export-components export function useThemeModeContext() { const context = useContext(ThemeModeContext); if (!context) { throw new Error('Theme context error.'); } return context; }