diff --git a/packages/mui-material/src/styles/createTheme.test.js b/packages/mui-material/src/styles/createTheme.test.js index 9ec0a1a2a776e5..3c24d90fe3f302 100644 --- a/packages/mui-material/src/styles/createTheme.test.js +++ b/packages/mui-material/src/styles/createTheme.test.js @@ -4,7 +4,7 @@ import { createRenderer } from '@mui/internal-test-utils'; import Button from '@mui/material/Button'; import Box from '@mui/material/Box'; import { ThemeProvider, createTheme, styled } from '@mui/material/styles'; -import { deepOrange, green } from '@mui/material/colors'; +import { deepOrange, green, grey } from '@mui/material/colors'; import createPalette from './createPalette'; const lightPalette = createPalette({ mode: 'light' }); @@ -56,6 +56,114 @@ describe('createTheme', () => { expect(theme.palette.secondary.main).to.equal(green.A400); }); + it('should be customizable through `colorSchemes` node', () => { + const theme = createTheme({ + colorSchemes: { + dark: { + palette: { + background: { + default: grey[900], + }, + }, + }, + light: { + palette: { + background: { + default: grey[50], + }, + bg: { + main: grey[800], + dark: grey[700], + }, + }, + }, + }, + }); + expect(theme.colorSchemes.dark.palette.background.default).to.equal(grey[900]); + expect(theme.colorSchemes.light.palette.background.default).to.equal(grey[50]); + expect(theme.colorSchemes.light.palette.bg.main).to.equal(grey[800]); + expect(theme.colorSchemes.light.palette.bg.dark).to.equal(grey[700]); + expect(theme.palette.mode).to.equal('light'); + expect(theme.palette.background.default).to.equal(grey[50]); + }); + + it('should be customizable through `colorSchemes` node with non-existing fields', () => { + const theme = createTheme({ + colorSchemes: { + dark: { + opacity: { + disabled: 0.38, + }, + palette: { + gradient: 'linear-gradient(90deg, #000000 0%, #ffffff 100%)', + }, + }, + light: { + opacity: { + disabled: 0.5, + }, + palette: { + gradient: 'linear-gradient(90deg, #ffffff 0%, #000000 100%)', + }, + }, + }, + }); + expect(theme.colorSchemes.dark.opacity.disabled).to.equal(0.38); + expect(theme.colorSchemes.light.opacity.disabled).to.equal(0.5); + expect(theme.colorSchemes.dark.palette.gradient).to.equal( + 'linear-gradient(90deg, #000000 0%, #ffffff 100%)', + ); + expect(theme.colorSchemes.light.palette.gradient).to.equal( + 'linear-gradient(90deg, #ffffff 0%, #000000 100%)', + ); + }); + + it('should work with `palette` and `colorSchemes`', () => { + const theme = createTheme({ + palette: { + primary: { + main: '#27272a', + }, + background: { + default: '#f5f5f5', + }, + }, + colorSchemes: { + dark: true, + }, + }); + expect(theme.palette.primary.main).to.equal('#27272a'); + expect(theme.palette.background.default).to.equal('#f5f5f5'); + expect(theme.colorSchemes.light.palette.primary.main).to.equal('#27272a'); + expect(theme.colorSchemes.light.palette.background.default).to.equal('#f5f5f5'); + expect(theme.colorSchemes.dark.palette.primary.main).to.equal(darkPalette.primary.main); + expect(theme.colorSchemes.dark.palette.background.default).to.equal( + darkPalette.background.default, + ); + }); + + it('should work with `palette` and a custom `colorSchemes.dark`', () => { + const theme = createTheme({ + palette: { + background: { + default: '#f5f5f5', + }, + }, + colorSchemes: { + dark: { + palette: { + background: { + default: 'red', + }, + }, + }, + }, + }); + expect(theme.palette.background.default).to.equal('#f5f5f5'); + expect(theme.colorSchemes.light.palette.background.default).to.equal('#f5f5f5'); + expect(theme.colorSchemes.dark.palette.background.default).to.equal('red'); + }); + describe('CSS variables', () => { it('should have default light with media selector if no `palette` and colorSchemes.dark is provided ', () => { const theme = createTheme({ diff --git a/packages/mui-material/src/styles/createTheme.ts b/packages/mui-material/src/styles/createTheme.ts index dd2b26c6fbad65..36e92f1082edaf 100644 --- a/packages/mui-material/src/styles/createTheme.ts +++ b/packages/mui-material/src/styles/createTheme.ts @@ -22,7 +22,7 @@ function attachColorScheme( theme.colorSchemes[scheme] = { ...(colorScheme !== true && colorScheme), palette: createPalette({ - ...(colorScheme === true ? {} : colorScheme), + ...(colorScheme === true ? {} : colorScheme.palette), mode: scheme, } as any), // cast type to skip module augmentation test }; @@ -72,24 +72,46 @@ export default function createTheme( }; if (cssVariables === false) { - const theme = createThemeNoVars(options as ThemeOptions, ...args) as unknown as Theme & { + if (!('colorSchemes' in options)) { + // Behaves exactly as v5 + return createThemeNoVars(options as ThemeOptions, ...args); + } + + let paletteOptions = palette; + if (!('palette' in options)) { + if (colorSchemesInput[defaultColorSchemeInput]) { + if (colorSchemesInput[defaultColorSchemeInput] !== true) { + paletteOptions = colorSchemesInput[defaultColorSchemeInput].palette; + } else if (defaultColorSchemeInput === 'dark') { + // @ts-ignore to prevent the module augmentation test from failing + paletteOptions = { mode: 'dark' }; + } + } + } + + const theme = createThemeNoVars( + { ...options, palette: paletteOptions } as ThemeOptions, + ...args, + ) as unknown as Theme & { defaultColorScheme?: 'light' | 'dark'; colorSchemes?: Partial>; }; - if (!('colorSchemes' in options)) { - return theme; - } - theme.defaultColorScheme = defaultColorSchemeInput; theme.colorSchemes = colorSchemesInput as Record; if (theme.palette.mode === 'light') { - theme.colorSchemes.light = { palette: theme.palette } as ColorSystem; + theme.colorSchemes.light = { + ...(colorSchemesInput.light !== true && colorSchemesInput.light), + palette: theme.palette, + } as ColorSystem; attachColorScheme(theme, 'dark', colorSchemesInput.dark); } if (theme.palette.mode === 'dark') { - theme.colorSchemes.dark = { palette: theme.palette } as ColorSystem; + theme.colorSchemes.dark = { + ...(colorSchemesInput.dark !== true && colorSchemesInput.dark), + palette: theme.palette, + } as ColorSystem; attachColorScheme(theme, 'light', colorSchemesInput.light); }