Merge pull request #2 from rkheftan/chore/theme
chore(theme): define palette and typographies and override mui styles…
This commit is contained in:
16
index.html
16
index.html
@@ -5,6 +5,22 @@
|
|||||||
<!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
|
<!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Harmony club</title>
|
<title>Harmony club</title>
|
||||||
|
<!-- this script add for preventing initial theme flashing -->
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
try {
|
||||||
|
const THEME_STORAGE_KEY = 'mui-mode';
|
||||||
|
const DARK_THEME_CLASS_NAME = 'dark';
|
||||||
|
const savedMode = localStorage.getItem(THEME_STORAGE_KEY);
|
||||||
|
const prefersDark = window.matchMedia(
|
||||||
|
'(prefers-color-scheme: dark)',
|
||||||
|
).matches;
|
||||||
|
if (savedMode === 'dark' || (!savedMode && prefersDark)) {
|
||||||
|
document.documentElement.classList.add(DARK_THEME_CLASS_NAME);
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
64
package-lock.json
generated
64
package-lock.json
generated
@@ -11,12 +11,15 @@
|
|||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.1",
|
"@emotion/styled": "^11.14.1",
|
||||||
"@mui/material": "^7.2.0",
|
"@mui/material": "^7.2.0",
|
||||||
|
"@mui/stylis-plugin-rtl": "^7.2.0",
|
||||||
"i18next": "^25.3.0",
|
"i18next": "^25.3.0",
|
||||||
"i18next-browser-languagedetector": "^8.2.0",
|
"i18next-browser-languagedetector": "^8.2.0",
|
||||||
"i18next-http-backend": "^3.0.2",
|
"i18next-http-backend": "^3.0.2",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"react-i18next": "^15.6.0"
|
"react-i18next": "^15.6.0",
|
||||||
|
"stylis": "^4.3.6",
|
||||||
|
"stylis-plugin-rtl": "^2.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.29.0",
|
"@eslint/js": "^9.29.0",
|
||||||
@@ -358,6 +361,12 @@
|
|||||||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
|
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@emotion/babel-plugin/node_modules/stylis": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@emotion/cache": {
|
"node_modules/@emotion/cache": {
|
||||||
"version": "11.14.0",
|
"version": "11.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz",
|
||||||
@@ -371,6 +380,12 @@
|
|||||||
"stylis": "4.2.0"
|
"stylis": "4.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@emotion/cache/node_modules/stylis": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@emotion/hash": {
|
"node_modules/@emotion/hash": {
|
||||||
"version": "0.9.2",
|
"version": "0.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
|
||||||
@@ -1298,6 +1313,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@mui/stylis-plugin-rtl": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mui/stylis-plugin-rtl/-/stylis-plugin-rtl-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-x+9UMuAuB82dbzxxFeCoZEZaLzdBVOSlkSEhFu8iJgsEmwJXJ9l09NsiONw8sJlp7J5etpGEiafDz0XSM/C/Fw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.27.6",
|
||||||
|
"cssjanus": "^2.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/mui-org"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"stylis": "4.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@mui/system": {
|
"node_modules/@mui/system": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/system/-/system-7.2.0.tgz",
|
||||||
@@ -2414,6 +2449,15 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cssjanus": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cssjanus/-/cssjanus-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-ZZXXn51SnxRxAZ6fdY7mBDPmA4OZd83q/J9Gdqz3YmE9TUq+9tZl+tdOnCi7PpNygI6PEkehj9rgifv5+W8a5A==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
@@ -3911,11 +3955,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/stylis": {
|
"node_modules/stylis": {
|
||||||
"version": "4.2.0",
|
"version": "4.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz",
|
||||||
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==",
|
"integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/stylis-plugin-rtl": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/stylis-plugin-rtl/-/stylis-plugin-rtl-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-q6xIkri6fBufIO/sV55md2CbgS5c6gg9EhSVATtHHCdOnbN/jcI0u3lYhNVeuI65c4lQPo67g8xmq5jrREvzlg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cssjanus": "^2.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"stylis": "4.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/supports-color": {
|
"node_modules/supports-color": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
|
|||||||
@@ -14,12 +14,15 @@
|
|||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.1",
|
"@emotion/styled": "^11.14.1",
|
||||||
"@mui/material": "^7.2.0",
|
"@mui/material": "^7.2.0",
|
||||||
|
"@mui/stylis-plugin-rtl": "^7.2.0",
|
||||||
"i18next": "^25.3.0",
|
"i18next": "^25.3.0",
|
||||||
"i18next-browser-languagedetector": "^8.2.0",
|
"i18next-browser-languagedetector": "^8.2.0",
|
||||||
"i18next-http-backend": "^3.0.2",
|
"i18next-http-backend": "^3.0.2",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
"react-i18next": "^15.6.0"
|
"react-i18next": "^15.6.0",
|
||||||
|
"stylis": "^4.3.6",
|
||||||
|
"stylis-plugin-rtl": "^2.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.29.0",
|
"@eslint/js": "^9.29.0",
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"helloWorld": "hello world"
|
"helloWorld": "hello world"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"helloWorld": "سلام دنیا"
|
"helloWorld": "سلام دنیا"
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/App.tsx
21
src/App.tsx
@@ -1,4 +1,4 @@
|
|||||||
import { CssBaseline } from '@mui/material';
|
import { Box, CssBaseline, TextField, useColorScheme } from '@mui/material';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { LanguageManager } from './components/LanguageManager';
|
import { LanguageManager } from './components/LanguageManager';
|
||||||
@@ -13,9 +13,28 @@ function App() {
|
|||||||
<div style={{ padding: '16px' }}>
|
<div style={{ padding: '16px' }}>
|
||||||
<h1>{t('helloWorld')}</h1>
|
<h1>{t('helloWorld')}</h1>
|
||||||
<p>The main content and router will go here.</p>
|
<p>The main content and router will go here.</p>
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
|
||||||
|
<ThemeToggleButton />
|
||||||
|
<TextField label={t('helloWorld')} />
|
||||||
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
||||||
|
import { Button } from '@mui/material';
|
||||||
|
|
||||||
|
export const ThemeToggleButton = () => {
|
||||||
|
const { mode, setMode } = useColorScheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
onClick={() => setMode(mode === 'light' ? 'dark' : 'light')}
|
||||||
|
>
|
||||||
|
Switch to {mode === 'light' ? 'Dark' : 'Light'} Mode
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect } from 'react';
|
import { useLayoutEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -8,10 +8,10 @@ import { useTranslation } from 'react-i18next';
|
|||||||
export const LanguageManager = () => {
|
export const LanguageManager = () => {
|
||||||
const { i18n } = useTranslation();
|
const { i18n } = useTranslation();
|
||||||
|
|
||||||
useEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const handleLanguageChange = (lng: string) => {
|
const handleLanguageChange = (lng: string) => {
|
||||||
document.documentElement.dir = i18n.dir(lng);
|
document.documentElement.setAttribute('dir', i18n.dir(lng));
|
||||||
document.documentElement.lang = lng;
|
document.documentElement.setAttribute('lang', lng);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set initial values on component mount
|
// Set initial values on component mount
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ i18n
|
|||||||
.use(initReactI18next) // Passes i18n down to react-i18next
|
.use(initReactI18next) // Passes i18n down to react-i18next
|
||||||
.init({
|
.init({
|
||||||
supportedLngs: ['en', 'fa'], // Supported languages
|
supportedLngs: ['en', 'fa'], // Supported languages
|
||||||
fallbackLng: 'fa',
|
fallbackLng: 'en',
|
||||||
detection: {
|
detection: {
|
||||||
order: ['localStorage', 'cookie', 'navigator'],
|
order: ['localStorage', 'cookie', 'navigator'],
|
||||||
caches: ['localStorage', 'cookie'],
|
caches: ['localStorage', 'cookie'],
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { I18nextProvider } from 'react-i18next';
|
import { I18nextProvider } from 'react-i18next';
|
||||||
import i18n from '@/config/i18n';
|
import i18n from '@/config/i18n';
|
||||||
|
import { CustomThemeProvider } from './CustomThemeProvider';
|
||||||
|
import { RtlProvider } from './RtlProvider';
|
||||||
|
|
||||||
export const AppProviders: React.FC<{ children: React.ReactNode }> = ({
|
export const AppProviders: React.FC<{ children: React.ReactNode }> = ({
|
||||||
children,
|
children,
|
||||||
}) => {
|
}) => {
|
||||||
return <I18nextProvider i18n={i18n}>{children}</I18nextProvider>;
|
return (
|
||||||
|
<I18nextProvider i18n={i18n}>
|
||||||
|
<RtlProvider>
|
||||||
|
<CustomThemeProvider>{children}</CustomThemeProvider>
|
||||||
|
</RtlProvider>
|
||||||
|
</I18nextProvider>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
38
src/providers/CustomThemeProvider.tsx
Normal file
38
src/providers/CustomThemeProvider.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import { createTheme, ThemeProvider } from '@mui/material';
|
||||||
|
import { darkPalette, lightPalette } from '@/theme/palette';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { typography } from '@/theme/typography';
|
||||||
|
|
||||||
|
export const CustomThemeProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const { i18n } = useTranslation();
|
||||||
|
|
||||||
|
const theme = useMemo(() => {
|
||||||
|
const direction = i18n.dir(i18n.language);
|
||||||
|
|
||||||
|
return createTheme({
|
||||||
|
direction: direction,
|
||||||
|
colorSchemes: {
|
||||||
|
light: {
|
||||||
|
palette: lightPalette,
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
palette: darkPalette,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cssVariables: {
|
||||||
|
colorSchemeSelector: 'class',
|
||||||
|
},
|
||||||
|
spacing: 8,
|
||||||
|
typography: typography,
|
||||||
|
});
|
||||||
|
}, [i18n]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeProvider theme={theme} defaultMode="system">
|
||||||
|
{children}
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
25
src/providers/RtlProvider.tsx
Normal file
25
src/providers/RtlProvider.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { CacheProvider } from '@emotion/react';
|
||||||
|
import createCache from '@emotion/cache';
|
||||||
|
import rtlPlugin from 'stylis-plugin-rtl';
|
||||||
|
|
||||||
|
// This provider configures Emotion's cache to support RTL.
|
||||||
|
export const RtlProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const { i18n } = useTranslation();
|
||||||
|
const [cache, setCache] = useState(createCache({ key: 'css' }));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const newDir = i18n.dir(i18n.language);
|
||||||
|
|
||||||
|
const newCache = createCache({
|
||||||
|
key: 'css',
|
||||||
|
stylisPlugins: newDir === 'rtl' ? [rtlPlugin] : [],
|
||||||
|
});
|
||||||
|
setCache(newCache);
|
||||||
|
}, [i18n, i18n.language]);
|
||||||
|
|
||||||
|
return <CacheProvider value={cache}>{children}</CacheProvider>;
|
||||||
|
};
|
||||||
46
src/theme/color.type.ts
Normal file
46
src/theme/color.type.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import type {
|
||||||
|
PaletteColor,
|
||||||
|
TypeAction,
|
||||||
|
TypeBackground,
|
||||||
|
TypeText,
|
||||||
|
} from '@mui/material';
|
||||||
|
import type { PaletteColorOptions } from 'node_modules/@mui/material';
|
||||||
|
|
||||||
|
export interface Palette {
|
||||||
|
primary: {
|
||||||
|
dark: PaletteColorOptions;
|
||||||
|
light: PaletteColorOptions;
|
||||||
|
};
|
||||||
|
secondary: {
|
||||||
|
dark: PaletteColor;
|
||||||
|
light: PaletteColor;
|
||||||
|
};
|
||||||
|
action: {
|
||||||
|
dark: Partial<TypeAction>;
|
||||||
|
light: Partial<TypeAction>;
|
||||||
|
};
|
||||||
|
error: {
|
||||||
|
dark: PaletteColor;
|
||||||
|
light: PaletteColor;
|
||||||
|
};
|
||||||
|
warning: {
|
||||||
|
dark: PaletteColor;
|
||||||
|
light: PaletteColor;
|
||||||
|
};
|
||||||
|
info: {
|
||||||
|
dark: PaletteColor;
|
||||||
|
light: PaletteColor;
|
||||||
|
};
|
||||||
|
success: {
|
||||||
|
dark: PaletteColor;
|
||||||
|
light: PaletteColor;
|
||||||
|
};
|
||||||
|
background: {
|
||||||
|
dark: Partial<TypeBackground>;
|
||||||
|
light: Partial<TypeBackground>;
|
||||||
|
};
|
||||||
|
text: {
|
||||||
|
dark: Partial<TypeText>;
|
||||||
|
light: Partial<TypeText>;
|
||||||
|
};
|
||||||
|
}
|
||||||
188
src/theme/colorTmp.ts
Normal file
188
src/theme/colorTmp.ts
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
export const PALETTE = {
|
||||||
|
primary: {
|
||||||
|
light: {
|
||||||
|
main: '#212121',
|
||||||
|
dark: '#000000',
|
||||||
|
light: '#616161',
|
||||||
|
contrastText: '#FFFFFF',
|
||||||
|
hover: '#21212104',
|
||||||
|
selected: '#21212108',
|
||||||
|
focus: '#21212112',
|
||||||
|
focusVisible: '#21212130',
|
||||||
|
outlinedBorder: '#21212150',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
main: '#64b5f6',
|
||||||
|
light: '#90caf9',
|
||||||
|
dark: '#42a5f5',
|
||||||
|
contrastText: 'rgba(0, 0, 0, 0.87)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
light: {
|
||||||
|
main: '#FF5722',
|
||||||
|
dark: '#E64A19',
|
||||||
|
light: '#FF8A65',
|
||||||
|
contrastText: '#FFFFFF',
|
||||||
|
hover: '#FF572204',
|
||||||
|
selected: '#FF572208',
|
||||||
|
focus: '#FF572212',
|
||||||
|
focusVisible: '#FF572230',
|
||||||
|
outlinedBorder: '#FF572250',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
main: '#ce93d8',
|
||||||
|
light: '#f3e5f5',
|
||||||
|
dark: '#ab47bc',
|
||||||
|
contrastText: 'rgba(0, 0, 0, 0.87)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
light: {
|
||||||
|
action: '#00000056',
|
||||||
|
hover: '#00000004',
|
||||||
|
selected: '#00000008',
|
||||||
|
focus: '#00000012',
|
||||||
|
disabled: '#00000038',
|
||||||
|
disabledBackground: '#00000012',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
action: '#FFFFFF56',
|
||||||
|
hover: '#FFFFFF04',
|
||||||
|
selected: '#FFFFFF08',
|
||||||
|
focus: '#FFFFFF12',
|
||||||
|
disabled: '#FFFFFF38',
|
||||||
|
disabledBackground: '#FFFFFF12',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
light: {
|
||||||
|
main: '#E53935',
|
||||||
|
dark: '#C62828',
|
||||||
|
light: '#EF5350',
|
||||||
|
contrast: '#FFFFFF',
|
||||||
|
hover: '#D32F2F04',
|
||||||
|
selected: '#D32F2F08',
|
||||||
|
focusVisible: '#D32F2F30',
|
||||||
|
outlinedBorder: '#D32F2F50',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
main: '#E53935',
|
||||||
|
dark: '#C62828',
|
||||||
|
light: '#EF5350',
|
||||||
|
contrast: '#FFFFFF',
|
||||||
|
hover: '#D32F2F04',
|
||||||
|
selected: '#D32F2F08',
|
||||||
|
focusVisible: '#D32F2F30',
|
||||||
|
outlinedBorder: '#D32F2F50',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
warning: {
|
||||||
|
light: {
|
||||||
|
main: '#EF6C00',
|
||||||
|
dark: '#E65100',
|
||||||
|
light: '#FF9800',
|
||||||
|
contrast: '#FFFFFF',
|
||||||
|
hover: '#EF6C0004',
|
||||||
|
selected: '#EF6C0008',
|
||||||
|
focusVisible: '#EF6C0030',
|
||||||
|
outlinedBorder: '#EF6C0050',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
main: '#EF6C00',
|
||||||
|
dark: '#E65100',
|
||||||
|
light: '#FF9800',
|
||||||
|
contrast: '#FFFFFF',
|
||||||
|
hover: '#EF6C0004',
|
||||||
|
selected: '#EF6C0008',
|
||||||
|
focusVisible: '#EF6C0030',
|
||||||
|
outlinedBorder: '#EF6C0050',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
light: {
|
||||||
|
main: '#29B6F6',
|
||||||
|
dark: '#0288D1',
|
||||||
|
light: '#4FC3F7',
|
||||||
|
contrast: '#FFFFFF',
|
||||||
|
hover: '#0288D104',
|
||||||
|
selected: '#0288D108',
|
||||||
|
focusVisible: '#0288D130',
|
||||||
|
outlinedBorder: '#0288D150',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
main: '#29B6F6',
|
||||||
|
dark: '#0288D1',
|
||||||
|
light: '#4FC3F7',
|
||||||
|
contrast: '#FFFFFF',
|
||||||
|
hover: '#0288D104',
|
||||||
|
selected: '#0288D108',
|
||||||
|
focusVisible: '#0288D130',
|
||||||
|
outlinedBorder: '#0288D150',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
light: {
|
||||||
|
main: '#43A047',
|
||||||
|
dark: '#1B5E20',
|
||||||
|
light: '#81C784',
|
||||||
|
contrast: '#FFFFFF',
|
||||||
|
hover: '#2E7D3204',
|
||||||
|
selected: '#2E7D3208',
|
||||||
|
focusVisible: '#2E7D3230',
|
||||||
|
outlinedBorder: '#2E7D3250',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
main: '#43A047',
|
||||||
|
dark: '#1B5E20',
|
||||||
|
light: '#81C784',
|
||||||
|
contrast: '#FFFFFF',
|
||||||
|
hover: '#2E7D3204',
|
||||||
|
selected: '#2E7D3208',
|
||||||
|
focusVisible: '#2E7D3230',
|
||||||
|
outlinedBorder: '#2E7D3250',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Background colors
|
||||||
|
background: {
|
||||||
|
light: {
|
||||||
|
default: '#FAFAFA',
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
default: '#121212',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Text colors
|
||||||
|
text: {
|
||||||
|
light: {
|
||||||
|
primary: '#000000',
|
||||||
|
secondary: '#424242',
|
||||||
|
tertiary: '#757575',
|
||||||
|
disabled: '#00000038',
|
||||||
|
hover: '#00000004',
|
||||||
|
selected: '#00000008',
|
||||||
|
divider: '#E0E0E0',
|
||||||
|
focus: '#00000012',
|
||||||
|
focusVisible: '#00000030',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
primary: '#FFFFFF',
|
||||||
|
secondary: '#424242',
|
||||||
|
tertiary: '#757575',
|
||||||
|
disabled: '#FFFFFF38',
|
||||||
|
hover: '#FFFFFF04',
|
||||||
|
selected: '#FFFFFF08',
|
||||||
|
divider: '#E0E0E0',
|
||||||
|
focus: '#FFFFFF12',
|
||||||
|
focusVisible: '#FFFFFF30',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
134
src/theme/colors.ts
Normal file
134
src/theme/colors.ts
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import type { Palette } from './color.type';
|
||||||
|
|
||||||
|
export const PALETTE: Palette = {
|
||||||
|
primary: {
|
||||||
|
light: {
|
||||||
|
main: '#212121',
|
||||||
|
dark: '#000000',
|
||||||
|
light: '#616161',
|
||||||
|
contrastText: '#FFFFFF',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
main: '#64b5f6',
|
||||||
|
light: '#90caf9',
|
||||||
|
dark: '#42a5f5',
|
||||||
|
contrastText: 'rgba(0, 0, 0, 0.87)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
light: {
|
||||||
|
main: '#FF5722',
|
||||||
|
dark: '#E64A19',
|
||||||
|
light: '#FF8A65',
|
||||||
|
contrastText: '#FFFFFF',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
main: '#ce93d8',
|
||||||
|
light: '#f3e5f5',
|
||||||
|
dark: '#ab47bc',
|
||||||
|
contrastText: 'rgba(0, 0, 0, 0.87)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
light: {
|
||||||
|
hover: '#00000004',
|
||||||
|
selected: '#00000008',
|
||||||
|
focus: '#00000012',
|
||||||
|
disabled: '#00000038',
|
||||||
|
disabledBackground: '#00000012',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
hover: '#FFFFFF04',
|
||||||
|
selected: '#FFFFFF08',
|
||||||
|
focus: '#FFFFFF12',
|
||||||
|
disabled: '#FFFFFF38',
|
||||||
|
disabledBackground: '#FFFFFF12',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
light: {
|
||||||
|
main: '#E53935',
|
||||||
|
dark: '#C62828',
|
||||||
|
light: '#EF5350',
|
||||||
|
contrastText: '#FFFFFF',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
main: '#E53935',
|
||||||
|
dark: '#C62828',
|
||||||
|
light: '#EF5350',
|
||||||
|
contrastText: '#FFFFFF',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
warning: {
|
||||||
|
light: {
|
||||||
|
main: '#EF6C00',
|
||||||
|
dark: '#E65100',
|
||||||
|
light: '#FF9800',
|
||||||
|
contrastText: '#FFFFFF',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
main: '#EF6C00',
|
||||||
|
dark: '#E65100',
|
||||||
|
light: '#FF9800',
|
||||||
|
contrastText: '#FFFFFF',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
light: {
|
||||||
|
main: '#29B6F6',
|
||||||
|
dark: '#0288D1',
|
||||||
|
light: '#4FC3F7',
|
||||||
|
contrastText: '#FFFFFF',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
main: '#29B6F6',
|
||||||
|
dark: '#0288D1',
|
||||||
|
light: '#4FC3F7',
|
||||||
|
contrastText: '#FFFFFF',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
light: {
|
||||||
|
main: '#43A047',
|
||||||
|
dark: '#1B5E20',
|
||||||
|
light: '#81C784',
|
||||||
|
contrastText: '#FFFFFF',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
main: '#43A047',
|
||||||
|
dark: '#1B5E20',
|
||||||
|
light: '#81C784',
|
||||||
|
contrastText: '#FFFFFF',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Background colors
|
||||||
|
background: {
|
||||||
|
light: {
|
||||||
|
default: '#FAFAFA',
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
default: '#121212',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Text colors
|
||||||
|
text: {
|
||||||
|
light: {
|
||||||
|
primary: '#000000',
|
||||||
|
secondary: '#424242',
|
||||||
|
disabled: '#00000038',
|
||||||
|
},
|
||||||
|
// TODO
|
||||||
|
dark: {
|
||||||
|
primary: '#FFFFFF',
|
||||||
|
secondary: '#424242',
|
||||||
|
disabled: '#FFFFFF38',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
28
src/theme/palette.ts
Normal file
28
src/theme/palette.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { type PaletteOptions } from '@mui/material/styles';
|
||||||
|
import { PALETTE } from './colors';
|
||||||
|
|
||||||
|
export const lightPalette: PaletteOptions = {
|
||||||
|
mode: 'light',
|
||||||
|
primary: PALETTE.primary.light,
|
||||||
|
secondary: PALETTE.secondary.light,
|
||||||
|
action: PALETTE.action.light,
|
||||||
|
error: PALETTE.error.light,
|
||||||
|
success: PALETTE.success.light,
|
||||||
|
warning: PALETTE.warning.light,
|
||||||
|
info: PALETTE.info.light,
|
||||||
|
background: PALETTE.background.light,
|
||||||
|
text: PALETTE.text.light,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const darkPalette: PaletteOptions = {
|
||||||
|
mode: 'dark',
|
||||||
|
primary: PALETTE.primary.dark,
|
||||||
|
secondary: PALETTE.secondary.dark,
|
||||||
|
action: PALETTE.action.dark,
|
||||||
|
error: PALETTE.error.dark,
|
||||||
|
success: PALETTE.success.dark,
|
||||||
|
warning: PALETTE.warning.dark,
|
||||||
|
info: PALETTE.info.dark,
|
||||||
|
background: PALETTE.background.dark,
|
||||||
|
text: PALETTE.text.dark,
|
||||||
|
};
|
||||||
65
src/theme/typography.ts
Normal file
65
src/theme/typography.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
// No need for a function, just a static object
|
||||||
|
export const typography = {
|
||||||
|
fontFamily: ['Roboto', 'sans-serif'].join(','),
|
||||||
|
fontWeightRegular: 400,
|
||||||
|
fontWeightMedium: 500,
|
||||||
|
fontWeightBold: 700,
|
||||||
|
|
||||||
|
h1: {
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: '6rem', // 96px
|
||||||
|
lineHeight: 1.17,
|
||||||
|
},
|
||||||
|
h2: {
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: '3.75rem', // 60px
|
||||||
|
lineHeight: 1.2,
|
||||||
|
},
|
||||||
|
h3: {
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: '3rem', // 48px
|
||||||
|
lineHeight: 1.17,
|
||||||
|
},
|
||||||
|
h4: {
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: '2.125rem', // 34px
|
||||||
|
lineHeight: 1.24,
|
||||||
|
},
|
||||||
|
h5: {
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: '1.5rem', // 24px
|
||||||
|
lineHeight: 1.35,
|
||||||
|
},
|
||||||
|
h6: {
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: '1.25rem', // 20px
|
||||||
|
lineHeight: 1.6,
|
||||||
|
},
|
||||||
|
subtitle1: {
|
||||||
|
fontSize: '1rem', // 16px
|
||||||
|
fontWeight: 500,
|
||||||
|
},
|
||||||
|
subtitle2: {
|
||||||
|
fontSize: '.785rem', // 16px
|
||||||
|
fontWeight: 500,
|
||||||
|
},
|
||||||
|
body1: {
|
||||||
|
fontSize: '1rem', // 16px
|
||||||
|
fontWeight: 400,
|
||||||
|
lineHeight: 1.5,
|
||||||
|
},
|
||||||
|
body2: {
|
||||||
|
fontSize: '0.875rem', // 14px
|
||||||
|
fontWeight: 400,
|
||||||
|
lineHeight: 1.5,
|
||||||
|
},
|
||||||
|
caption: {
|
||||||
|
fontSize: '0.75rem', // 12px
|
||||||
|
fontWeight: 400,
|
||||||
|
lineHeight: 1.5,
|
||||||
|
},
|
||||||
|
overline: {
|
||||||
|
fontSize: '0.75rem', // 12px
|
||||||
|
fontWeight: 400,
|
||||||
|
},
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user