Refactor themes structure

This commit is contained in:
Bill Thornton
2025-12-02 14:43:03 -05:00
parent 7bbfa02c4a
commit d3793f02eb
17 changed files with 205 additions and 165 deletions

View File

@@ -18,7 +18,7 @@ import BangRedirect from 'components/router/BangRedirect';
import { createRouterHistory } from 'components/router/routerHistory';
import { LayoutMode } from 'constants/layoutMode';
import browser from 'scripts/browser';
import appTheme from 'themes/themes';
import appTheme from 'themes';
import { ThemeStorageManager } from 'themes/themeStorageManager';
const layoutMode = browser.tv ? LayoutMode.Tv : localStorage.getItem(LAYOUT_SETTING_KEY);

View File

@@ -1,4 +1,4 @@
@use '../styles/mixins' as *;
@use '../../styles/mixins' as *;
@use './palette' as palette;
// Theme options

View File

@@ -0,0 +1,17 @@
import { buildCustomColorScheme } from 'themes/utils';
/** The Apple TV inspired color scheme. */
const theme = buildCustomColorScheme({
palette: {
mode: 'light',
background: {
default: '#d5e9f2',
paper: '#fff'
},
AppBar: {
defaultBg: '#bcbcbc'
}
}
});
export default theme;

View File

@@ -0,0 +1,15 @@
import { buildCustomColorScheme } from 'themes/utils';
/** The "Blue Radiance" color scheme. */
const theme = buildCustomColorScheme({
palette: {
background: {
paper: '#011432'
},
AppBar: {
defaultBg: '#011432'
}
}
});
export default theme;

20
src/themes/dark/index.ts Normal file
View File

@@ -0,0 +1,20 @@
import type { ColorSystemOptions } from '@mui/material/styles';
import merge from 'lodash-es/merge';
import { DEFAULT_COLOR_SCHEME } from '../_base/theme';
/** The default "Dark" color scheme. */
const theme = merge<ColorSystemOptions, ColorSystemOptions, ColorSystemOptions>(
{},
DEFAULT_COLOR_SCHEME,
{
palette: {
SnackbarContent: {
bg: '#303030',
color: 'rgba(255, 255, 255, 0.87)'
}
}
}
);
export default theme;

View File

@@ -1,5 +1,5 @@
/* Import the base theme */
@use '../base';
@use '../_base/theme';
/* Card background color variants */
.defaultCardBackground1 {

30
src/themes/index.ts Normal file
View File

@@ -0,0 +1,30 @@
import { createTheme } from '@mui/material/styles';
import { DEFAULT_THEME_OPTIONS } from './_base/theme';
import appletv from './appletv';
import blueradiance from './blueradiance';
import dark from './dark';
import light from './light';
import purplehaze from './purplehaze';
import wmc from './wmc';
/** The default theme containing all color scheme variants. */
const DEFAULT_THEME = createTheme({
cssVariables: {
cssVarPrefix: 'jf',
colorSchemeSelector: '[data-theme="%s"]',
disableCssColorScheme: true
},
defaultColorScheme: 'dark',
...DEFAULT_THEME_OPTIONS,
colorSchemes: {
appletv,
blueradiance,
dark,
light,
purplehaze,
wmc
}
});
export default DEFAULT_THEME;

40
src/themes/light/index.ts Normal file
View File

@@ -0,0 +1,40 @@
import type { ColorSystemOptions } from '@mui/material/styles';
import merge from 'lodash-es/merge';
import { DEFAULT_COLOR_SCHEME } from '../_base/theme';
/** The "Light" color scheme. */
const theme = merge<ColorSystemOptions, ColorSystemOptions, ColorSystemOptions>(
{},
DEFAULT_COLOR_SCHEME,
{
palette: {
mode: 'light',
background: {
default: '#f2f2f2',
paper: '#e8e8e8'
},
text: {
primary: '#000',
secondary: 'rgba(0, 0, 0, 0.87)'
},
action: {
focus: '#bbb',
hover: '#ddd'
},
Alert: {
infoFilledBg: '#fff3a5',
infoFilledColor: '#000'
},
AppBar: {
defaultBg: '#e8e8e8'
},
Button: {
inheritContainedBg: '#d8d8d8',
inheritContainedHoverBg: '#ccc'
}
}
}
);
export default theme;

View File

@@ -1,8 +1,8 @@
@use '../../styles/mixins' as *;
@use '../palette' as palette;
@use '../_base/palette' as palette;
/* Import the base theme with overrides */
@use '../base' with (
@use '../_base/theme' with (
// Theme options
$dark: false,

View File

@@ -0,0 +1,21 @@
import { buildCustomColorScheme } from 'themes/utils';
/** The "Purple Haze" color scheme. */
const theme = buildCustomColorScheme({
palette: {
background: {
paper: '#000420'
},
primary: {
main: '#48c3c8'
},
secondary: {
main: '#ff77f1'
},
AppBar: {
defaultBg: '#000420'
}
}
});
export default theme;

19
src/themes/styles.d.ts vendored Normal file
View File

@@ -0,0 +1,19 @@
import '@mui/material/styles';
/** Extend MUI types to include our customizations. */
declare module '@mui/material/styles' {
interface ColorSchemeOverrides {
appletv: true;
blueradiance: true;
purplehaze: true;
wmc: true;
}
interface Palette {
starIcon: Palette['primary'];
}
interface PaletteOptions {
starIcon?: PaletteOptions['primary'];
}
}

View File

@@ -1,159 +0,0 @@
import { type ColorSystemOptions, createTheme, extendTheme } from '@mui/material/styles';
import merge from 'lodash-es/merge';
import { DEFAULT_COLOR_SCHEME, DEFAULT_THEME_OPTIONS } from './defaults';
/** Extend MUI types to include our customizations. */
declare module '@mui/material/styles' {
interface ColorSchemeOverrides {
appletv: true;
blueradiance: true;
purplehaze: true;
wmc: true;
}
interface Palette {
starIcon: Palette['primary'];
}
interface PaletteOptions {
starIcon?: PaletteOptions['primary'];
}
}
/** The default built-in MUI theme. */
const defaultMuiTheme = extendTheme({
// @ts-expect-error The default theme does not include our custom color schemes
colorSchemes: { dark: true, light: true }
});
/**
* Default color schemes ('dark' or 'light') will automatically be merged with MUI's corresponding default color
* scheme. For custom schemes, we need to merge these manually.
*/
const buildCustomColorScheme = (options: ColorSystemOptions) => merge<ColorSystemOptions, ColorSystemOptions | undefined, ColorSystemOptions, ColorSystemOptions>(
{},
options.palette?.mode === 'light' ? defaultMuiTheme.colorSchemes.light : defaultMuiTheme.colorSchemes.dark,
DEFAULT_COLOR_SCHEME,
options
);
/** The Apple TV inspired color scheme. */
const appletv = buildCustomColorScheme({
palette: {
mode: 'light',
background: {
default: '#d5e9f2',
paper: '#fff'
},
AppBar: {
defaultBg: '#bcbcbc'
}
}
});
/** The "Blue Radiance" color scheme. */
const blueradiance = buildCustomColorScheme({
palette: {
background: {
paper: '#011432'
},
AppBar: {
defaultBg: '#011432'
}
}
});
/** The default "Dark" color scheme. */
const dark = merge({}, DEFAULT_COLOR_SCHEME, {
palette: {
SnackbarContent: {
bg: '#303030',
color: 'rgba(255, 255, 255, 0.87)'
}
}
});
/** The "Light" color scheme. */
const light = merge<ColorSystemOptions, ColorSystemOptions, ColorSystemOptions>({}, DEFAULT_COLOR_SCHEME, {
palette: {
mode: 'light',
background: {
default: '#f2f2f2',
paper: '#e8e8e8'
},
text: {
primary: '#000',
secondary: 'rgba(0, 0, 0, 0.87)'
},
action: {
focus: '#bbb',
hover: '#ddd'
},
Alert: {
infoFilledBg: '#fff3a5',
infoFilledColor: '#000'
},
AppBar: {
defaultBg: '#e8e8e8'
},
Button: {
inheritContainedBg: '#d8d8d8',
inheritContainedHoverBg: '#ccc'
}
}
});
/** The "Purple Haze" color scheme. */
const purplehaze = buildCustomColorScheme({
palette: {
background: {
paper: '#000420'
},
primary: {
main: '#48c3c8'
},
secondary: {
main: '#ff77f1'
},
AppBar: {
defaultBg: '#000420'
}
}
});
/** The Windows Media Center inspired color scheme. */
const wmc = buildCustomColorScheme({
palette: {
background: {
paper: '#0c2450'
},
AppBar: {
defaultBg: '#0c2450'
}
}
});
/** All color scheme variants in the app. */
export const COLOR_SCHEMES = {
appletv,
blueradiance,
dark,
light,
purplehaze,
wmc
};
/** The default theme containing all color scheme variants. */
const DEFAULT_THEME = createTheme({
cssVariables: {
cssVarPrefix: 'jf',
colorSchemeSelector: '[data-theme="%s"]',
disableCssColorScheme: true
},
defaultColorScheme: 'dark',
...DEFAULT_THEME_OPTIONS,
colorSchemes: COLOR_SCHEMES
});
export default DEFAULT_THEME;

22
src/themes/utils.ts Normal file
View File

@@ -0,0 +1,22 @@
import { type ColorSystemOptions, extendTheme } from '@mui/material/styles';
import merge from 'lodash-es/merge';
import { DEFAULT_COLOR_SCHEME } from './_base/theme';
/** The default built-in MUI theme. */
const defaultMuiTheme = extendTheme({
// @ts-expect-error The default theme does not include our custom color schemes
colorSchemes: { dark: true, light: true }
});
/**
* Default color schemes ('dark' or 'light') will automatically be merged with MUI's corresponding default color
* scheme. For custom schemes, we need to merge these manually.
*/
export const buildCustomColorScheme = (options: ColorSystemOptions) =>
merge<ColorSystemOptions, ColorSystemOptions | undefined, ColorSystemOptions, ColorSystemOptions>(
{},
options.palette?.mode === 'light' ? defaultMuiTheme.colorSchemes.light : defaultMuiTheme.colorSchemes.dark,
DEFAULT_COLOR_SCHEME,
options
);

15
src/themes/wmc/index.ts Normal file
View File

@@ -0,0 +1,15 @@
import { buildCustomColorScheme } from 'themes/utils';
/** The Windows Media Center inspired color scheme. */
const theme = buildCustomColorScheme({
palette: {
background: {
paper: '#0c2450'
},
AppBar: {
defaultBg: '#0c2450'
}
}
});
export default theme;

View File

@@ -6,7 +6,7 @@ import { createRoot } from 'react-dom/client';
import { ApiProvider } from 'hooks/useApi';
import { UserSettingsProvider } from 'hooks/useUserSettings';
import { WebConfigProvider } from 'hooks/useWebConfig';
import appTheme from 'themes/themes';
import appTheme from 'themes';
import { queryClient } from 'utils/query/queryClient';
export const renderComponent = <P extends object> (