Merge branch 'feat/VersionsExplorer' of https://git.popa-popa.ru/DIKER/popa-launcher into feat/VersionsExplorer
This commit is contained in:
@ -20,6 +20,7 @@ import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
|
|||||||
import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
|
import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
|
||||||
import PersonIcon from '@mui/icons-material/Person';
|
import PersonIcon from '@mui/icons-material/Person';
|
||||||
import SettingsIcon from '@mui/icons-material/Settings';
|
import SettingsIcon from '@mui/icons-material/Settings';
|
||||||
|
import { useTheme } from '@mui/material/styles';
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
electron: {
|
electron: {
|
||||||
@ -48,6 +49,7 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const tabsWrapperRef = useRef<HTMLDivElement | null>(null);
|
const tabsWrapperRef = useRef<HTMLDivElement | null>(null);
|
||||||
const tabsRootRef = useRef<HTMLDivElement | null>(null);
|
const tabsRootRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
const theme = useTheme();
|
||||||
|
|
||||||
const updateGradientVars = useCallback(() => {
|
const updateGradientVars = useCallback(() => {
|
||||||
const root = tabsRootRef.current;
|
const root = tabsRootRef.current;
|
||||||
@ -71,7 +73,8 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const path = location.pathname || '';
|
const path = location.pathname || '';
|
||||||
const isAuthPage = path.startsWith('/login') || path.startsWith('/registration');
|
const isAuthPage =
|
||||||
|
path.startsWith('/login') || path.startsWith('/registration');
|
||||||
|
|
||||||
const TAB_ROUTES: Array<{
|
const TAB_ROUTES: Array<{
|
||||||
value: number;
|
value: number;
|
||||||
@ -198,26 +201,7 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
|
|
||||||
// Функция для получения количества монет
|
// Функция для получения количества монет
|
||||||
|
|
||||||
const tabBaseSx = {
|
const tabBaseSx = [{ fontSize: '0.7em' }, theme.launcher.topbar.tabBase];
|
||||||
color: 'white',
|
|
||||||
fontFamily: 'Benzin-Bold',
|
|
||||||
fontSize: '0.7em',
|
|
||||||
transition: 'all 0.3s ease',
|
|
||||||
'&:hover': {
|
|
||||||
color: 'rgb(170, 170, 170)',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const activeTabSx = {
|
|
||||||
color: 'transparent',
|
|
||||||
WebkitTextFillColor: 'transparent',
|
|
||||||
backgroundImage: 'var(--tabs-grad)',
|
|
||||||
backgroundRepeat: 'no-repeat',
|
|
||||||
backgroundSize: 'var(--tabs-w) 100%',
|
|
||||||
backgroundPosition: 'calc(-1 * var(--active-x)) 0',
|
|
||||||
WebkitBackgroundClip: 'text',
|
|
||||||
backgroundClip: 'text',
|
|
||||||
};
|
|
||||||
|
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
localStorage.removeItem('launcher_config');
|
localStorage.removeItem('launcher_config');
|
||||||
@ -263,7 +247,8 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('skin-updated', handler as EventListener);
|
window.addEventListener('skin-updated', handler as EventListener);
|
||||||
return () => window.removeEventListener('skin-updated', handler as EventListener);
|
return () =>
|
||||||
|
window.removeEventListener('skin-updated', handler as EventListener);
|
||||||
}, [loadSkin]);
|
}, [loadSkin]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -278,7 +263,8 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
className={isAuthPage ? undefined : 'glass-ui'}
|
className={isAuthPage ? undefined : 'glass-ui'}
|
||||||
sx={{
|
sx={[
|
||||||
|
{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
top: 0,
|
top: 0,
|
||||||
@ -291,14 +277,9 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
},
|
||||||
// убрать если не оч
|
theme.launcher.topbar.firstBox,
|
||||||
|
]}
|
||||||
// стиль как в Registration
|
|
||||||
background: isAuthPage ?
|
|
||||||
'none' : 'linear-gradient(71deg, rgba(242,113,33,0.18) 0%, rgba(233,64,205,0.14) 70%, rgba(138,35,135,0.16) 100%)',
|
|
||||||
boxShadow: isAuthPage ? 'none' : '0 8px 30px rgba(0,0,0,0.35)',
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{/* Левая часть */}
|
{/* Левая часть */}
|
||||||
<Box
|
<Box
|
||||||
@ -314,20 +295,16 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
onClick={() => handleLaunchPage()}
|
onClick={() => handleLaunchPage()}
|
||||||
sx={{
|
sx={[
|
||||||
|
{
|
||||||
width: '3em',
|
width: '3em',
|
||||||
height: '3em',
|
height: '3em',
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
border: 'unset',
|
|
||||||
color: 'white',
|
|
||||||
minWidth: 'unset',
|
minWidth: 'unset',
|
||||||
minHeight: 'unset',
|
minHeight: 'unset',
|
||||||
transition: 'transform 0.3s ease',
|
|
||||||
'&:hover': {
|
|
||||||
transform: 'scale(1.2)',
|
|
||||||
...(document.body.classList.contains('reduce-motion') ? { transform: 'none' } : null),
|
|
||||||
},
|
},
|
||||||
}}
|
theme.launcher.topbar.backButton,
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
<ArrowBackRoundedIcon />
|
<ArrowBackRoundedIcon />
|
||||||
</Button>
|
</Button>
|
||||||
@ -339,7 +316,7 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
// старый вариант
|
// старый вариант
|
||||||
sx={{
|
sx={{
|
||||||
borderBottom: 1,
|
borderBottom: 1,
|
||||||
borderColor: 'transparent',
|
...theme.launcher.topbar.tabsBox,
|
||||||
// '& .MuiTabs-indicator': {
|
// '& .MuiTabs-indicator': {
|
||||||
// backgroundColor: 'rgba(255, 77, 77, 1)',
|
// backgroundColor: 'rgba(255, 77, 77, 1)',
|
||||||
// },
|
// },
|
||||||
@ -381,61 +358,40 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
scrollButtons={false}
|
scrollButtons={false}
|
||||||
disableRipple={true}
|
disableRipple={true}
|
||||||
sx={{
|
sx={{
|
||||||
// один градиент на весь Tabs
|
...theme.launcher.topbar.tabs,
|
||||||
'--tabs-grad': 'linear-gradient(90deg, #F27121 0%, #E940CD 50%, #8A2387 100%)',
|
|
||||||
|
|
||||||
// активный текст показывает “срез” общего градиента
|
|
||||||
'& .MuiTab-root.Mui-selected': {
|
|
||||||
color: 'transparent',
|
|
||||||
backgroundImage: 'var(--tabs-grad)',
|
|
||||||
backgroundRepeat: 'no-repeat',
|
|
||||||
backgroundSize: 'var(--tabs-w) 100%',
|
|
||||||
backgroundPosition: 'calc(-1 * var(--active-x)) 0',
|
|
||||||
WebkitBackgroundClip: 'text',
|
|
||||||
backgroundClip: 'text',
|
|
||||||
},
|
|
||||||
|
|
||||||
// подчёркивание тоже из того же “единого” градиента
|
|
||||||
'& .MuiTabs-indicator': {
|
|
||||||
height: '2px',
|
|
||||||
backgroundImage: 'var(--tabs-grad)',
|
|
||||||
backgroundRepeat: 'no-repeat',
|
|
||||||
backgroundSize: 'var(--tabs-w) 100%',
|
|
||||||
backgroundPosition: 'calc(-1 * var(--active-x)) 0',
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Tab
|
<Tab
|
||||||
label="Новости"
|
label="Новости"
|
||||||
disableRipple={true}
|
disableRipple={true}
|
||||||
sx={{
|
sx={[
|
||||||
...tabBaseSx,
|
...tabBaseSx,
|
||||||
...(selectedTab === 0 ? activeTabSx : null),
|
selectedTab === 0 ? theme.launcher.topbar.tabActive : null,
|
||||||
}}
|
]}
|
||||||
/>
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
label="Версии"
|
label="Версии"
|
||||||
disableRipple={true}
|
disableRipple={true}
|
||||||
sx={{
|
sx={[
|
||||||
...tabBaseSx,
|
...tabBaseSx,
|
||||||
...(selectedTab === 1 ? activeTabSx : null),
|
selectedTab === 1 ? theme.launcher.topbar.tabActive : null,
|
||||||
}}
|
]}
|
||||||
/>
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
label="Магазин"
|
label="Магазин"
|
||||||
disableRipple={true}
|
disableRipple={true}
|
||||||
sx={{
|
sx={[
|
||||||
...tabBaseSx,
|
...tabBaseSx,
|
||||||
...(selectedTab === 2 ? activeTabSx : null),
|
selectedTab === 2 ? theme.launcher.topbar.tabActive : null,
|
||||||
}}
|
]}
|
||||||
/>
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
label="Рынок"
|
label="Рынок"
|
||||||
disableRipple={true}
|
disableRipple={true}
|
||||||
sx={{
|
sx={[
|
||||||
...tabBaseSx,
|
...tabBaseSx,
|
||||||
...(selectedTab === 3 ? activeTabSx : null),
|
selectedTab === 3 ? theme.launcher.topbar.tabActive : null,
|
||||||
}}
|
]}
|
||||||
/>
|
/>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</CustomTooltip>
|
</CustomTooltip>
|
||||||
@ -507,6 +463,7 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
width: '3em',
|
width: '3em',
|
||||||
height: '3em',
|
height: '3em',
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
|
...theme.launcher.topbar.windowControlButton,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
@ -517,7 +474,7 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M 7 19 h 10 c 0.55 0 1 0.45 1 1 s -0.45 1 -1 1 H 7 c -0.55 0 -1 -0.45 -1 -1 s 0.45 -1 1 -1"
|
d="M 7 19 h 10 c 0.55 0 1 0.45 1 1 s -0.45 1 -1 1 H 7 c -0.55 0 -1 -0.45 -1 -1 s 0.45 -1 1 -1"
|
||||||
fill="white"
|
fill={theme.launcher.topbar.windowControlIcon.color}
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</Button>
|
</Button>
|
||||||
@ -531,9 +488,12 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
width: '3em',
|
width: '3em',
|
||||||
height: '3em',
|
height: '3em',
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
|
...theme.launcher.topbar.windowControlButton,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CloseRoundedIcon sx={{ color: 'white' }} />
|
<CloseRoundedIcon
|
||||||
|
sx={{ color: theme.launcher.topbar.windowControlIcon.color }}
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
<Menu
|
<Menu
|
||||||
@ -553,11 +513,7 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
mt: '0.5vw',
|
mt: '0.5vw',
|
||||||
borderRadius: '1vw',
|
borderRadius: '1vw',
|
||||||
minWidth: '16vw',
|
minWidth: '16vw',
|
||||||
color: 'white',
|
...theme.launcher.topbar.menuPaper,
|
||||||
bgcolor: 'rgba(0,0,0,0.82)',
|
|
||||||
backdropFilter: 'blur(10px)',
|
|
||||||
border: '1px solid rgba(233,64,205,0.25)',
|
|
||||||
boxShadow: '0 18px 40px rgba(0,0,0,0.55)',
|
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -581,10 +537,7 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
|
|
||||||
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
|
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
<Typography
|
<Typography
|
||||||
sx={{
|
sx={[{ fontSize: '2vw' }, theme.launcher.topbar.menuUsername]}
|
||||||
fontFamily: 'Benzin-Bold',
|
|
||||||
fontSize: '2vw',
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{username || 'Игрок'}
|
{username || 'Игрок'}
|
||||||
</Typography>
|
</Typography>
|
||||||
@ -603,22 +556,17 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Divider sx={{ my: '0.4vw', borderColor: 'rgba(255,255,255,0.08)' }} />
|
<Divider sx={{ my: '0.4vw', ...theme.launcher.topbar.menuDivider }} />
|
||||||
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleAvatarMenuClose();
|
handleAvatarMenuClose();
|
||||||
navigate('/profile');
|
navigate('/profile');
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={[
|
||||||
fontFamily: 'Benzin-Bold',
|
{ fontSize: '1.5vw', gap: '0.5vw', py: '0.7vw' },
|
||||||
fontSize: '1.5vw',
|
theme.launcher.topbar.menuItem,
|
||||||
gap: '0.5vw',
|
]}
|
||||||
py: '0.7vw',
|
|
||||||
'&:hover': {
|
|
||||||
bgcolor: 'rgba(255,77,77,0.15)',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<PersonIcon sx={{ fontSize: '2vw' }} /> Профиль
|
<PersonIcon sx={{ fontSize: '2vw' }} /> Профиль
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@ -629,15 +577,10 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
handleAvatarMenuClose();
|
handleAvatarMenuClose();
|
||||||
navigate('/dailyquests');
|
navigate('/dailyquests');
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={[
|
||||||
fontFamily: 'Benzin-Bold',
|
{ fontSize: '1.5vw', gap: '0.5vw', py: '0.7vw' },
|
||||||
fontSize: '1.5vw',
|
theme.launcher.topbar.menuItem,
|
||||||
gap: '0.5vw',
|
]}
|
||||||
py: '0.7vw',
|
|
||||||
'&:hover': {
|
|
||||||
bgcolor: 'rgba(255,77,77,0.15)',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<CalendarMonthIcon sx={{ fontSize: '2vw' }} /> Ежедневные задания
|
<CalendarMonthIcon sx={{ fontSize: '2vw' }} /> Ежедневные задания
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@ -648,15 +591,10 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
handleAvatarMenuClose();
|
handleAvatarMenuClose();
|
||||||
navigate('/daily');
|
navigate('/daily');
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={[
|
||||||
fontFamily: 'Benzin-Bold',
|
{ fontSize: '1.5vw', gap: '0.5vw', py: '0.7vw' },
|
||||||
fontSize: '1.5vw',
|
theme.launcher.topbar.menuItem,
|
||||||
gap: '0.5vw',
|
]}
|
||||||
py: '0.7vw',
|
|
||||||
'&:hover': {
|
|
||||||
bgcolor: 'rgba(255,77,77,0.15)',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<EmojiEventsIcon sx={{ fontSize: '2vw' }} /> Ежедневная награда
|
<EmojiEventsIcon sx={{ fontSize: '2vw' }} /> Ежедневная награда
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@ -666,20 +604,15 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
handleAvatarMenuClose();
|
handleAvatarMenuClose();
|
||||||
navigate('/settings');
|
navigate('/settings');
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={[
|
||||||
fontFamily: 'Benzin-Bold',
|
{ fontSize: '1.5vw', gap: '0.5vw', py: '0.7vw' },
|
||||||
fontSize: '1.5vw',
|
theme.launcher.topbar.menuItem,
|
||||||
gap: '0.5vw',
|
]}
|
||||||
py: '0.7vw',
|
|
||||||
'&:hover': {
|
|
||||||
bgcolor: 'rgba(255,77,77,0.15)',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<SettingsIcon sx={{ fontSize: '2vw' }} /> Настройки
|
<SettingsIcon sx={{ fontSize: '2vw' }} /> Настройки
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
<Divider sx={{ my: '0.4vw', borderColor: 'rgba(255,255,255,0.08)' }} />
|
<Divider sx={{ my: '0.4vw', ...theme.launcher.topbar.menuDivider }} />
|
||||||
{!isLoginPage && !isRegistrationPage && username && (
|
{!isLoginPage && !isRegistrationPage && username && (
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
@ -688,27 +621,15 @@ export default function TopBar({ onRegister, username }: TopBarProps) {
|
|||||||
handleAvatarMenuClose();
|
handleAvatarMenuClose();
|
||||||
logout();
|
logout();
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={[
|
||||||
|
{
|
||||||
width: '8vw',
|
width: '8vw',
|
||||||
height: '3vw',
|
height: '3vw',
|
||||||
borderRadius: '2.5vw',
|
|
||||||
fontFamily: 'Benzin-Bold',
|
|
||||||
fontSize: '1.2vw',
|
fontSize: '1.2vw',
|
||||||
background:
|
|
||||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
|
||||||
color: 'white',
|
|
||||||
border: 'none',
|
|
||||||
transition: 'transform 0.3s ease',
|
|
||||||
'&:hover': {
|
|
||||||
background:
|
|
||||||
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
|
||||||
transform: 'scale(1.01)',
|
|
||||||
...(document.body.classList.contains('reduce-motion') ? { transform: 'none' } : null),
|
|
||||||
boxShadow: '0 4px 15px rgba(242, 113, 33, 0.4)',
|
|
||||||
},
|
|
||||||
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.3)',
|
|
||||||
m: '0 0 0 18vw',
|
m: '0 0 0 18vw',
|
||||||
}}
|
},
|
||||||
|
theme.launcher.topbar.logoutButton,
|
||||||
|
]}
|
||||||
>
|
>
|
||||||
Выйти
|
Выйти
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -1,9 +1,18 @@
|
|||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
|
||||||
|
import { ThemeProvider, CssBaseline } from '@mui/material';
|
||||||
|
import { defaultTheme } from '../theme/themes'; // <-- поправь путь, если themes.ts лежит в другом месте
|
||||||
|
|
||||||
const container = document.getElementById('root') as HTMLElement;
|
const container = document.getElementById('root') as HTMLElement;
|
||||||
const root = createRoot(container);
|
const root = createRoot(container);
|
||||||
root.render(<App />);
|
|
||||||
|
root.render(
|
||||||
|
<ThemeProvider theme={defaultTheme}>
|
||||||
|
<CssBaseline />
|
||||||
|
<App />
|
||||||
|
</ThemeProvider>,
|
||||||
|
);
|
||||||
|
|
||||||
// calling IPC exposed from preload script
|
// calling IPC exposed from preload script
|
||||||
window.electron?.ipcRenderer.once('ipc-example', (arg) => {
|
window.electron?.ipcRenderer.once('ipc-example', (arg) => {
|
||||||
|
|||||||
176
src/theme/themes.ts
Normal file
176
src/theme/themes.ts
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
import { createTheme, SxProps, Theme } from '@mui/material/styles';
|
||||||
|
|
||||||
|
declare module '@mui/material/styles' {
|
||||||
|
interface Theme {
|
||||||
|
launcher: {
|
||||||
|
fonts: {
|
||||||
|
default: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
gradients: {
|
||||||
|
accent: string;
|
||||||
|
tabs: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
topbar: {
|
||||||
|
firstBox: SxProps<Theme>;
|
||||||
|
backButton: SxProps<Theme>;
|
||||||
|
tabsBox: {
|
||||||
|
borderColor: string;
|
||||||
|
};
|
||||||
|
tabs: SxProps<Theme>;
|
||||||
|
tabBase: SxProps<Theme>;
|
||||||
|
tabActive: SxProps<Theme>;
|
||||||
|
menuPaper: SxProps<Theme>;
|
||||||
|
menuDivider: SxProps<Theme>;
|
||||||
|
menuItem: SxProps<Theme>;
|
||||||
|
menuUsername: SxProps<Theme>;
|
||||||
|
logoutButton: SxProps<Theme>;
|
||||||
|
windowControlIcon: {
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
|
windowControlButton: SxProps<Theme>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ThemeOptions {
|
||||||
|
launcher?: Theme['launcher'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultTheme = createTheme({
|
||||||
|
palette: {
|
||||||
|
mode: 'dark',
|
||||||
|
primary: { main: '#F27121' },
|
||||||
|
secondary: { main: '#E940CD' },
|
||||||
|
text: {
|
||||||
|
primary: '#FFFFFF',
|
||||||
|
secondary: 'rgba(255,255,255,0.7)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
launcher: {
|
||||||
|
fonts: {
|
||||||
|
default: 'Benzin-Bold',
|
||||||
|
},
|
||||||
|
|
||||||
|
gradients: {
|
||||||
|
accent: '#F27121 0%, #E940CD 50%, #8A2387 100%',
|
||||||
|
tabs: 'linear-gradient(71deg, rgba(242,113,33,0.18) 0%, rgba(233,64,205,0.14) 70%, rgba(138,35,135,0.16) 100%)',
|
||||||
|
},
|
||||||
|
|
||||||
|
topbar: {
|
||||||
|
firstBox: (theme: Theme) => ({
|
||||||
|
background: theme.launcher.gradients.tabs,
|
||||||
|
backdropFilter: 'blur(10px)',
|
||||||
|
boxShadow: '0 8px 30px rgba(0,0,0,0.35)',
|
||||||
|
}),
|
||||||
|
backButton: (theme: Theme) => ({
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
transition: 'transform 0.3s ease',
|
||||||
|
'&:hover': {
|
||||||
|
transform: 'scale(1.2)',
|
||||||
|
},
|
||||||
|
border: 'unset',
|
||||||
|
}),
|
||||||
|
tabsBox: {
|
||||||
|
borderColor: 'transparent',
|
||||||
|
},
|
||||||
|
tabs: {
|
||||||
|
// один градиент на весь Tabs
|
||||||
|
'--tabs-grad':
|
||||||
|
'linear-gradient(90deg, #F27121 0%, #E940CD 50%, #8A2387 100%)',
|
||||||
|
|
||||||
|
// активный текст показывает “срез” общего градиента
|
||||||
|
'& .MuiTab-root.Mui-selected': {
|
||||||
|
color: 'transparent',
|
||||||
|
backgroundImage: 'var(--tabs-grad)',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundSize: 'var(--tabs-w) 100%',
|
||||||
|
backgroundPosition: 'calc(-1 * var(--active-x)) 0',
|
||||||
|
WebkitBackgroundClip: 'text',
|
||||||
|
backgroundClip: 'text',
|
||||||
|
},
|
||||||
|
|
||||||
|
// подчёркивание тоже из того же “единого” градиента
|
||||||
|
'& .MuiTabs-indicator': {
|
||||||
|
height: '2px',
|
||||||
|
backgroundImage: 'var(--tabs-grad)',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundSize: 'var(--tabs-w) 100%',
|
||||||
|
backgroundPosition: 'calc(-1 * var(--active-x)) 0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tabBase: (theme: Theme) => ({
|
||||||
|
color: 'white',
|
||||||
|
fontFamily: theme.launcher.fonts.default,
|
||||||
|
transition: 'all 0.3s ease',
|
||||||
|
'&:hover': {
|
||||||
|
color: 'rgb(170, 170, 170)',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
tabActive: {
|
||||||
|
color: 'transparent',
|
||||||
|
WebkitTextFillColor: 'transparent',
|
||||||
|
backgroundImage: 'var(--tabs-grad)',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundSize: 'var(--tabs-w) 100%',
|
||||||
|
backgroundPosition: 'calc(-1 * var(--active-x)) 0',
|
||||||
|
WebkitBackgroundClip: 'text',
|
||||||
|
backgroundClip: 'text',
|
||||||
|
},
|
||||||
|
menuPaper: {
|
||||||
|
color: 'white',
|
||||||
|
bgcolor: 'rgba(0,0,0,0.82)',
|
||||||
|
backdropFilter: 'blur(10px)',
|
||||||
|
border: '1px solid rgba(233,64,205,0.25)',
|
||||||
|
boxShadow: '0 18px 40px rgba(0,0,0,0.55)',
|
||||||
|
},
|
||||||
|
|
||||||
|
menuDivider: {
|
||||||
|
borderColor: 'rgba(255,255,255,0.08)',
|
||||||
|
},
|
||||||
|
|
||||||
|
menuItem: (theme: Theme) => ({
|
||||||
|
fontFamily: theme.launcher.fonts.default,
|
||||||
|
'&:hover': {
|
||||||
|
bgcolor: 'rgba(255,77,77,0.15)',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
menuUsername: (theme: Theme) => ({
|
||||||
|
fontFamily: theme.launcher.fonts.default,
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
}),
|
||||||
|
|
||||||
|
logoutButton: (theme: Theme) => ({
|
||||||
|
fontFamily: theme.launcher.fonts.default,
|
||||||
|
borderRadius: '2.5vw',
|
||||||
|
background:
|
||||||
|
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||||
|
color: 'white',
|
||||||
|
border: 'none',
|
||||||
|
transition: 'transform 0.3s ease',
|
||||||
|
'&:hover': {
|
||||||
|
background:
|
||||||
|
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)',
|
||||||
|
transform: 'scale(1.01)',
|
||||||
|
boxShadow: '0 4px 15px rgba(242, 113, 33, 0.4)',
|
||||||
|
},
|
||||||
|
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.3)',
|
||||||
|
}),
|
||||||
|
|
||||||
|
windowControlIcon: {
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
|
||||||
|
windowControlButton: {
|
||||||
|
// тут только “визуал”, размеры оставим в TopBar
|
||||||
|
'&:hover': {
|
||||||
|
bgcolor: 'rgba(255,255,255,0.06)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user