AppGlobalStyles.tsx
1 import { useMediaQuery } from '@mui/material'; 2 import CssBaseline from '@mui/material/CssBaseline'; 3 import { createTheme, ThemeProvider } from '@mui/material/styles'; 4 import { deepmerge } from '@mui/utils'; 5 import React, { ReactNode, useEffect, useMemo, useState } from 'react'; 6 7 import { getDesignTokens, getThemedComponents } from '../utils/theme'; 8 9 export const ColorModeContext = React.createContext({ 10 // eslint-disable-next-line @typescript-eslint/no-empty-function 11 toggleColorMode: () => {}, 12 }); 13 14 type Mode = 'light' | 'dark'; 15 16 /** 17 * Main Layout component which wrapps around the whole app 18 * @param param0 19 * @returns 20 */ 21 export function AppGlobalStyles({ children }: { children: ReactNode }) { 22 const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); 23 const [mode, setMode] = useState<Mode>(prefersDarkMode ? 'dark' : 'light'); 24 const colorMode = useMemo( 25 () => ({ 26 toggleColorMode: () => { 27 setMode((prevMode) => { 28 const newMode = prevMode === 'light' ? 'dark' : 'light'; 29 localStorage.setItem('colorMode', newMode); 30 return newMode; 31 }); 32 }, 33 }), 34 [] 35 ); 36 37 useEffect(() => { 38 const initialMode = localStorage?.getItem('colorMode') as Mode; 39 if (initialMode) { 40 setMode(initialMode); 41 } else if (prefersDarkMode) { 42 setMode('dark'); 43 } 44 }, []); 45 46 const theme = useMemo(() => { 47 const themeCreate = createTheme(getDesignTokens(mode)); 48 return deepmerge(themeCreate, getThemedComponents(themeCreate)); 49 }, [mode]); 50 51 return ( 52 <ColorModeContext.Provider value={colorMode}> 53 <ThemeProvider theme={theme}> 54 {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */} 55 <CssBaseline /> 56 57 {children} 58 </ThemeProvider> 59 </ColorModeContext.Provider> 60 ); 61 }