Switch to "colorSchemes" from "palette" API in mui theme

"colorSchemes" is the preferred api starting from mui v6
This commit is contained in:
schroda
2025-01-16 12:14:15 +01:00
parent 9255386b1c
commit a22a4bf546
14 changed files with 493 additions and 195 deletions

View File

@@ -11,12 +11,16 @@ import {
darken,
Direction,
lighten,
Palette,
responsiveFontSizes,
Theme,
TypeBackground,
useTheme,
} from '@mui/material/styles';
import { useCallback } from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies,no-restricted-imports
import { deepmerge } from '@mui/utils';
// eslint-disable-next-line no-restricted-imports
import { PaletteBackgroundChannel } from '@mui/material/styles/createThemeWithVars';
import { ThemeMode } from '@/modules/theme/contexts/ThemeModeContext.tsx';
import { MediaQuery } from '@/modules/core/utils/MediaQuery.tsx';
import { AppTheme, loadThemeFonts } from '@/modules/theme/services/AppThemes.ts';
@@ -25,6 +29,56 @@ import { applyStyles } from '@/modules/core/utils/ApplyStyles.ts';
const SCROLLBAR_SIZE = 14;
declare module '@mui/material/styles' {
interface CssThemeVariables {
enabled: true;
}
}
const getBackgroundColor = (
type: 'light' | 'dark',
appTheme: AppTheme,
theme: Theme,
setPureBlackMode: boolean = false,
): (Partial<TypeBackground> & Partial<PaletteBackgroundChannel>) | undefined => {
if (setPureBlackMode) {
return {
paper: '#111',
default: '#000',
};
}
if (type === 'light' && !!theme.colorSchemes.light) {
if (
typeof appTheme.muiTheme.colorSchemes?.light === 'object' &&
appTheme.muiTheme.colorSchemes.light.palette?.background
) {
return appTheme.muiTheme.colorSchemes.light.palette.background;
}
return {
paper: lighten(theme.colorSchemes.light.palette.primary.dark, 0.8),
default: lighten(theme.colorSchemes.light.palette.primary.dark, 0.9),
};
}
if (type === 'dark' && !!theme.colorSchemes.dark) {
if (
typeof appTheme.muiTheme.colorSchemes?.dark === 'object' &&
appTheme.muiTheme.colorSchemes.dark.palette?.background
) {
return appTheme.muiTheme.colorSchemes.dark.palette.background;
}
return {
paper: darken(theme.colorSchemes.dark.palette.primary.dark, 0.8),
default: darken(theme.colorSchemes.dark.palette.primary.dark, 0.9),
};
}
return undefined;
};
export const createTheme = (
themeMode: ThemeMode,
appTheme: AppTheme,
@@ -33,93 +87,78 @@ export const createTheme = (
) => {
const systemMode = MediaQuery.getSystemThemeMode();
const appThemeType = (appTheme.muiTheme.palette as any)?.type ?? appTheme.muiTheme.palette?.mode;
const isStaticThemeMode = !!appThemeType;
const appThemeMode = appThemeType === 'dark' ? ThemeMode.DARK : ThemeMode.LIGHT;
const staticThemeMode = isStaticThemeMode ? appThemeMode : undefined;
const mode = staticThemeMode ?? (themeMode === ThemeMode.SYSTEM ? systemMode : themeMode);
const mode = themeMode === ThemeMode.SYSTEM ? systemMode : themeMode;
const isDarkMode = mode === ThemeMode.DARK;
const setPureBlackMode = isDarkMode && pureBlackMode;
const baseTheme = createMuiTheme({
direction,
...appTheme.muiTheme,
palette: {
mode,
...(appTheme.muiTheme.palette ?? {}),
},
});
const themeForColors = createMuiTheme({ ...appTheme.muiTheme, defaultColorScheme: mode });
const backgroundTrueBlack: Palette['background'] = {
paper: '#111',
default: '#000',
};
const backgroundDark: Palette['background'] = {
paper: darken(baseTheme.palette.primary.dark, 0.75),
default: darken(baseTheme.palette.primary.dark, 0.85),
};
const backgroundLight: Palette['background'] = {
paper: lighten(baseTheme.palette.primary.dark, 0.8),
default: lighten(baseTheme.palette.primary.dark, 0.9),
};
const backgroundThemeMode = isDarkMode ? backgroundDark : backgroundLight;
const automaticBackground = setPureBlackMode ? backgroundTrueBlack : backgroundThemeMode;
const appThemeBackground = appTheme.muiTheme.palette?.background;
const requiresAutomaticBackground = setPureBlackMode || !appThemeBackground;
const background = requiresAutomaticBackground ? automaticBackground : appThemeBackground;
const colorTheme = createMuiTheme(baseTheme, {
palette: {
background,
},
});
const suwayomiTheme = createMuiTheme(colorTheme, {
components: {
...appTheme.muiTheme.components,
MuiUseMediaQuery: {
defaultProps: {
noSsr: true,
},
const suwayomiTheme = createMuiTheme(
deepmerge(appTheme.muiTheme, {
defaultColorScheme: mode,
direction,
colorSchemes: {
light: appTheme.muiTheme.colorSchemes?.light
? {
palette: {
background: getBackgroundColor('light', appTheme, themeForColors),
},
}
: undefined,
dark: appTheme.muiTheme.colorSchemes?.dark
? {
palette: {
background: getBackgroundColor('dark', appTheme, themeForColors, setPureBlackMode),
},
}
: undefined,
},
MuiCssBaseline: {
...appTheme.muiTheme.components?.MuiCssBaseline,
styleOverrides:
typeof appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides === 'object'
? {
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides,
'*::-webkit-scrollbar': applyStyles(CSS.supports('-webkit-touch-callout', 'none'), {
width: `${SCROLLBAR_SIZE}px`,
height: `${SCROLLBAR_SIZE}px`,
// @ts-ignore - '*::-webkit-scrollbar' is a valid key
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides?.[
'*::-webkit-scrollbar'
],
}),
'*::-webkit-scrollbar-thumb': applyStyles(CSS.supports('-webkit-touch-callout', 'none'), {
border: '4px solid rgba(0, 0, 0, 0)',
backgroundClip: 'padding-box',
borderRadius: '9999px',
backgroundColor: `${colorTheme.palette.primary[isDarkMode ? 'dark' : 'light']}`,
// @ts-ignore - '*::-webkit-scrollbar-thumb' is a valid key
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides?.[
'*::-webkit-scrollbar-thumb'
],
}),
'*::-webkit-scrollbar-thumb:hover': applyStyles(
CSS.supports('-webkit-touch-callout', 'none'),
{
borderWidth: '2px',
// @ts-ignore - '*::-webkit-scrollbar-thumb:hover' is a valid key
components: {
...appTheme.muiTheme.components,
MuiUseMediaQuery: {
defaultProps: {
noSsr: true,
},
},
MuiCssBaseline: {
...appTheme.muiTheme.components?.MuiCssBaseline,
styleOverrides:
typeof appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides === 'object'
? {
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides,
'*::-webkit-scrollbar': applyStyles(CSS.supports('-webkit-touch-callout', 'none'), {
width: `${SCROLLBAR_SIZE}px`,
height: `${SCROLLBAR_SIZE}px`,
// @ts-ignore - '*::-webkit-scrollbar' is a valid key
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides?.[
'*::-webkit-scrollbar-thumb:hover'
'*::-webkit-scrollbar'
],
},
),
}
: `
}),
'*::-webkit-scrollbar-thumb': applyStyles(
CSS.supports('-webkit-touch-callout', 'none'),
{
border: '4px solid rgba(0, 0, 0, 0)',
backgroundClip: 'padding-box',
borderRadius: '9999px',
backgroundColor: `${themeForColors.palette.primary[isDarkMode ? 'dark' : 'light']}`,
// @ts-ignore - '*::-webkit-scrollbar-thumb' is a valid key
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides?.[
'*::-webkit-scrollbar-thumb'
],
},
),
'*::-webkit-scrollbar-thumb:hover': applyStyles(
CSS.supports('-webkit-touch-callout', 'none'),
{
borderWidth: '2px',
// @ts-ignore - '*::-webkit-scrollbar-thumb:hover' is a valid key
...appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides?.[
'*::-webkit-scrollbar-thumb:hover'
],
},
),
}
: `
@supports not (-webkit-touch-callout: none) {
/* CSS for other than iOS devices */
*::-webkit-scrollbar {
@@ -130,7 +169,7 @@ export const createTheme = (
border: 4px solid rgba(0, 0, 0, 0);
background-clip: padding-box;
border-radius: 9999px;
background-color: ${colorTheme.palette.primary[isDarkMode ? 'dark' : 'light']};
background-color: ${themeForColors.palette.primary[isDarkMode ? 'dark' : 'light']};
}
*::-webkit-scrollbar-thumb:hover {
border-width: 2px;
@@ -139,9 +178,10 @@ export const createTheme = (
${appTheme.muiTheme.components?.MuiCssBaseline?.styleOverrides ?? ''}
}
`,
},
},
},
});
}),
);
return responsiveFontSizes(suwayomiTheme);
};