chore: App theme added
This commit is contained in:
717
package-lock.json
generated
717
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,9 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@emotion/react": "^11.14.0",
|
||||||
|
"@emotion/styled": "^11.14.1",
|
||||||
|
"@mui/material": "^7.2.0",
|
||||||
"i18next": "^25.3.0",
|
"i18next": "^25.3.0",
|
||||||
"i18next-http-backend": "^3.0.2",
|
"i18next-http-backend": "^3.0.2",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import './App.css';
|
import './App.css';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return <div>PlaceHolder</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Hello World</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
12
src/contexts/AppThemeContext.ts
Normal file
12
src/contexts/AppThemeContext.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import type { AppTheme } from '@/types/theme';
|
||||||
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
export interface AppThemeContextModel {
|
||||||
|
mode: AppTheme;
|
||||||
|
changeTheme: (theme: AppTheme) => void;
|
||||||
|
}
|
||||||
|
// The context is used by the LangaugeProvider
|
||||||
|
export const AppThemeContext = createContext<AppThemeContextModel>({
|
||||||
|
mode: 'default',
|
||||||
|
changeTheme: () => {},
|
||||||
|
});
|
||||||
21
src/hooks/useAppTheme.ts
Normal file
21
src/hooks/useAppTheme.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import {
|
||||||
|
AppThemeContext,
|
||||||
|
type AppThemeContextModel,
|
||||||
|
} from '@/contexts/AppThemeContext';
|
||||||
|
import { useTheme, type Theme } from '@mui/material';
|
||||||
|
import { useContext } from 'react';
|
||||||
|
|
||||||
|
export interface AppThemeHookModel extends AppThemeContextModel {
|
||||||
|
theme: Theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useAppTheme = (): AppThemeHookModel => {
|
||||||
|
const appThemeContext = useContext(AppThemeContext);
|
||||||
|
const muiTheme = useTheme();
|
||||||
|
|
||||||
|
return {
|
||||||
|
mode: appThemeContext.mode,
|
||||||
|
changeTheme: appThemeContext.changeTheme,
|
||||||
|
theme: muiTheme,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -4,11 +4,15 @@ import './index.css';
|
|||||||
import './lib/i18n';
|
import './lib/i18n';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import { LanguageProvider } from './providers/LanguageProvider';
|
import { LanguageProvider } from './providers/LanguageProvider';
|
||||||
|
import { createTheme, ThemeProvider } from '@mui/material';
|
||||||
|
import { AppThemeProvider } from './providers/ThemeProvider';
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<LanguageProvider>
|
<LanguageProvider>
|
||||||
<App />
|
<AppThemeProvider>
|
||||||
|
<App />
|
||||||
|
</AppThemeProvider>
|
||||||
</LanguageProvider>
|
</LanguageProvider>
|
||||||
</StrictMode>,
|
</StrictMode>,
|
||||||
);
|
);
|
||||||
|
|||||||
33
src/providers/ThemeProvider.tsx
Normal file
33
src/providers/ThemeProvider.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { useLayoutEffect, type JSX, type PropsWithChildren } from 'react';
|
||||||
|
import { useLocalStorage } from '@/hooks/useLocalStorage';
|
||||||
|
import type { AppTheme } from '@/types/theme';
|
||||||
|
import { AppThemeContext } from '@/contexts/AppThemeContext';
|
||||||
|
import { createTheme, ThemeProvider } from '@mui/material';
|
||||||
|
import { useLangauge } from '@/hooks/useLanguage';
|
||||||
|
|
||||||
|
export const AppThemeProvider = (props: PropsWithChildren): JSX.Element => {
|
||||||
|
const { language } = useLangauge();
|
||||||
|
const [currentThemeMode, setCurrentTheme] = useLocalStorage<AppTheme>(
|
||||||
|
'theme',
|
||||||
|
'default',
|
||||||
|
);
|
||||||
|
|
||||||
|
const muiTheme = createTheme({
|
||||||
|
direction: language === 'fa' ? 'rtl' : 'ltr',
|
||||||
|
});
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
document.body.setAttribute('theme', currentThemeMode);
|
||||||
|
}, [currentThemeMode]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppThemeContext.Provider
|
||||||
|
value={{
|
||||||
|
mode: currentThemeMode,
|
||||||
|
changeTheme: setCurrentTheme,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ThemeProvider theme={muiTheme}>{props.children}</ThemeProvider>
|
||||||
|
</AppThemeContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
1
src/types/theme.ts
Normal file
1
src/types/theme.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export type AppTheme = 'default' | 'dark';
|
||||||
Reference in New Issue
Block a user