;
+
+ScopedCssBaseline.propTypes /* remove-proptypes */ = {
+ // ----------------------------- Warning --------------------------------
+ // | These PropTypes are generated from the TypeScript type definitions |
+ // | To update them edit TypeScript types and run "yarn proptypes" |
+ // ----------------------------------------------------------------------
+ /**
+ * You can wrap a node.
+ */
+ children: PropTypes.node,
+ /**
+ * @ignore
+ */
+ className: PropTypes.string,
+ /**
+ * The component used for the root node.
+ * Either a string to use a HTML element or a component.
+ */
+ component: PropTypes.elementType,
+ /**
+ * Disable `color-scheme` CSS property.
+ *
+ * For more details, check out https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme
+ * For browser support, check out https://caniuse.com/?search=color-scheme
+ * @default false
+ */
+ disableColorScheme: PropTypes.bool,
+ /**
+ * The system prop that allows defining system overrides as well as additional CSS styles.
+ */
+ sx: PropTypes.oneOfType([
+ PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])),
+ PropTypes.func,
+ PropTypes.object,
+ ]),
+} as any;
+
+export default ScopedCssBaseline;
diff --git a/packages/mui-joy/src/ScopedCssBaseline/ScopedCssBaselineProps.ts b/packages/mui-joy/src/ScopedCssBaseline/ScopedCssBaselineProps.ts
new file mode 100644
index 00000000000000..653f7f0007ea2e
--- /dev/null
+++ b/packages/mui-joy/src/ScopedCssBaseline/ScopedCssBaselineProps.ts
@@ -0,0 +1,33 @@
+import { OverrideProps } from '@mui/types';
+import { SxProps } from '../styles/types';
+
+export type ScopedCssBaselineSlot = 'root';
+
+export interface ScopedCssBaselineTypeMap {
+ props: P & {
+ /**
+ * You can wrap a node.
+ */
+ children?: React.ReactNode;
+ /**
+ * Disable `color-scheme` CSS property.
+ *
+ * For more details, check out https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme
+ * For browser support, check out https://caniuse.com/?search=color-scheme
+ * @default false
+ */
+ disableColorScheme?: boolean;
+ /**
+ * The system prop that allows defining system overrides as well as additional CSS styles.
+ */
+ sx?: SxProps;
+ };
+ defaultComponent: D;
+}
+
+export type ScopedCssBaselineProps<
+ D extends React.ElementType = ScopedCssBaselineTypeMap['defaultComponent'],
+ P = { component?: React.ElementType },
+> = OverrideProps, D>;
+
+export interface ScopedCssBaselineOwnerState extends ScopedCssBaselineProps {}
diff --git a/packages/mui-joy/src/ScopedCssBaseline/index.ts b/packages/mui-joy/src/ScopedCssBaseline/index.ts
new file mode 100644
index 00000000000000..932d9e670454a8
--- /dev/null
+++ b/packages/mui-joy/src/ScopedCssBaseline/index.ts
@@ -0,0 +1,3 @@
+export { default } from './ScopedCssBaseline';
+export * from './ScopedCssBaselineProps';
+export { default as scopedCssBaselineClasses } from './scopedCssBaselineClasses';
diff --git a/packages/mui-joy/src/ScopedCssBaseline/scopedCssBaselineClasses.ts b/packages/mui-joy/src/ScopedCssBaseline/scopedCssBaselineClasses.ts
new file mode 100644
index 00000000000000..aff1b911f67bb9
--- /dev/null
+++ b/packages/mui-joy/src/ScopedCssBaseline/scopedCssBaselineClasses.ts
@@ -0,0 +1,16 @@
+import { generateUtilityClass, generateUtilityClasses } from '../className';
+
+export interface ScopedCssBaselineClasses {
+ /** Styles applied to the root element. */
+ root: string;
+}
+
+export type ScopedCssBaselineClassKey = keyof ScopedCssBaselineClasses;
+
+export function getScopedCssBaselineUtilityClass(slot: string): string {
+ return generateUtilityClass('JoyScopedCssBaseline', slot);
+}
+
+const scopedCssBaselineClasses = generateUtilityClasses('JoyScopedCssBaseline', ['root']);
+
+export default scopedCssBaselineClasses;
diff --git a/packages/mui-joy/src/index.ts b/packages/mui-joy/src/index.ts
index 92ed116c82b2b0..70c4d2017b0d73 100644
--- a/packages/mui-joy/src/index.ts
+++ b/packages/mui-joy/src/index.ts
@@ -1,6 +1,8 @@
export { default as colors } from './colors';
export * from './styles';
+export { default as GlobalStyles } from './GlobalStyles';
+
export { default as AspectRatio } from './AspectRatio';
export * from './AspectRatio';
@@ -52,6 +54,12 @@ export * from './ChipDelete';
export { default as Container } from './Container';
export * from './Container';
+export { default as CssBaseline } from './CssBaseline';
+export * from './CssBaseline';
+
+export { default as ScopedCssBaseline } from './ScopedCssBaseline';
+export * from './ScopedCssBaseline';
+
export { default as Divider } from './Divider';
export * from './Divider';
diff --git a/packages/mui-joy/src/styles/CssVarsProvider.tsx b/packages/mui-joy/src/styles/CssVarsProvider.tsx
index 55c61211c4e093..b86b5859a77721 100644
--- a/packages/mui-joy/src/styles/CssVarsProvider.tsx
+++ b/packages/mui-joy/src/styles/CssVarsProvider.tsx
@@ -4,6 +4,7 @@ import type { DefaultColorScheme, ExtendedColorScheme } from './types';
const shouldSkipGeneratingVar = (keys: string[]) =>
!!keys[0].match(/(typography|variants|breakpoints)/) ||
+ (keys[0] === 'palette' && !!keys[1]?.match(/^(mode)$/)) ||
(keys[0] === 'focus' && keys[1] !== 'thickness');
const { CssVarsProvider, useColorScheme, getInitColorSchemeScript } = createCssVarsProvider<
diff --git a/packages/mui-joy/src/styles/components.d.ts b/packages/mui-joy/src/styles/components.d.ts
index 5baebedd8c0476..2af2a749419865 100644
--- a/packages/mui-joy/src/styles/components.d.ts
+++ b/packages/mui-joy/src/styles/components.d.ts
@@ -45,6 +45,11 @@ import {
CircularProgressSlot,
} from '../CircularProgress/CircularProgressProps';
import { ContainerProps, ContainerSlot } from '../Container/ContainerProps';
+import {
+ ScopedCssBaselineProps,
+ ScopedCssBaselineOwnerState,
+ ScopedCssBaselineSlot,
+} from '../ScopedCssBaseline/ScopedCssBaselineProps';
import { DividerProps, DividerOwnerState, DividerSlot } from '../Divider/DividerProps';
import {
FormControlProps,
@@ -219,6 +224,10 @@ export interface Components {
defaultProps?: Partial;
styleOverrides?: OverridesStyleRules;
};
+ JoyScopedCssBaseline?: {
+ defaultProps?: Partial;
+ styleOverrides?: OverridesStyleRules;
+ };
JoyDivider?: {
defaultProps?: Partial;
styleOverrides?: OverridesStyleRules;
diff --git a/packages/mui-joy/src/styles/defaultTheme.test.js b/packages/mui-joy/src/styles/defaultTheme.test.js
index 8b322ccc577d99..cbc5e23cdd2fc9 100644
--- a/packages/mui-joy/src/styles/defaultTheme.test.js
+++ b/packages/mui-joy/src/styles/defaultTheme.test.js
@@ -26,6 +26,7 @@ describe('extendTheme', () => {
'variants',
'vars',
'cssVarPrefix',
+ 'getColorSchemeSelector',
]).to.includes(field);
});
});
diff --git a/packages/mui-joy/src/styles/defaultTheme.ts b/packages/mui-joy/src/styles/defaultTheme.ts
index 79b8c71965ddcc..a1ac1faca92723 100644
--- a/packages/mui-joy/src/styles/defaultTheme.ts
+++ b/packages/mui-joy/src/styles/defaultTheme.ts
@@ -59,6 +59,7 @@ export const getThemeWithVars = (
shadow,
palette,
},
+ getColorSchemeSelector: () => '&',
} as unknown as Theme;
};
diff --git a/packages/mui-joy/src/styles/extendTheme.spec.ts b/packages/mui-joy/src/styles/extendTheme.spec.ts
index a7af37166e146d..0871826b7a4f54 100644
--- a/packages/mui-joy/src/styles/extendTheme.spec.ts
+++ b/packages/mui-joy/src/styles/extendTheme.spec.ts
@@ -14,6 +14,7 @@ import { ChipOwnerState } from '@mui/joy/Chip';
import { ChipDeleteOwnerState } from '@mui/joy/ChipDelete';
import { CircularProgressOwnerState } from '@mui/joy/CircularProgress';
import { ContainerProps } from '@mui/joy/Container';
+import { ScopedCssBaselineOwnerState } from '@mui/joy/ScopedCssBaseline';
import { DividerOwnerState } from '@mui/joy/Divider';
import { FormControlOwnerState } from '@mui/joy/FormControl';
import { FormHelperTextOwnerState } from '@mui/joy/FormHelperText';
@@ -353,6 +354,19 @@ extendTheme({
},
},
},
+ JoyScopedCssBaseline: {
+ defaultProps: {
+ disableColorScheme: true,
+ },
+ styleOverrides: {
+ root: ({ ownerState }) => {
+ expectType, typeof ownerState>(
+ ownerState,
+ );
+ return {};
+ },
+ },
+ },
JoyDivider: {
defaultProps: {
orientation: 'vertical',
diff --git a/packages/mui-joy/src/styles/extendTheme.ts b/packages/mui-joy/src/styles/extendTheme.ts
index 2bc8df32d808a4..afd06089b45c5b 100644
--- a/packages/mui-joy/src/styles/extendTheme.ts
+++ b/packages/mui-joy/src/styles/extendTheme.ts
@@ -142,6 +142,7 @@ export default function extendTheme(themeOptions?: CssVarsThemeOptions): Theme {
const lightColorSystem = {
palette: {
+ mode: 'light',
primary: {
...colors.blue,
...createLightModeVariantVariables('primary'),
@@ -243,6 +244,7 @@ export default function extendTheme(themeOptions?: CssVarsThemeOptions): Theme {
};
const darkColorSystem = {
palette: {
+ mode: 'dark',
primary: {
...colors.blue,
...createDarkModeVariantVariables('primary'),
diff --git a/packages/mui-joy/src/styles/types/colorSystem.ts b/packages/mui-joy/src/styles/types/colorSystem.ts
index cb31adff718f05..3614b41f336417 100644
--- a/packages/mui-joy/src/styles/types/colorSystem.ts
+++ b/packages/mui-joy/src/styles/types/colorSystem.ts
@@ -135,6 +135,7 @@ export interface PaletteSuccess extends PaletteRange {}
export interface PaletteWarning extends PaletteRange {}
export interface Palette {
+ mode: 'light' | 'dark';
primary: PalettePrimary;
neutral: PaletteNeutral;
danger: PaletteDanger;
diff --git a/packages/mui-joy/src/styles/types/theme.ts b/packages/mui-joy/src/styles/types/theme.ts
index f278f59b7d7ae0..72847868e87b67 100644
--- a/packages/mui-joy/src/styles/types/theme.ts
+++ b/packages/mui-joy/src/styles/types/theme.ts
@@ -43,7 +43,6 @@ type NormalizeVars = ConcatDeep>;
export interface RuntimeColorSystem extends Omit {
palette: ColorSystem['palette'] & {
- mode: 'light' | 'dark';
colorScheme: DefaultColorScheme | ExtendedColorScheme;
};
}
@@ -59,7 +58,10 @@ export interface ThemeScales {
letterSpacing: LetterSpacing;
}
-export interface ThemeVars extends ThemeScales, ColorSystem {}
+interface ColorSystemVars extends Omit {
+ palette: Omit;
+}
+export interface ThemeVars extends ThemeScales, ColorSystemVars {}
export interface ThemeCssVarOverrides {}
diff --git a/packages/mui-material/src/CssBaseline/CssBaseline.js b/packages/mui-material/src/CssBaseline/CssBaseline.js
index 2b32bd57898e17..c2a55eb7ebbebe 100644
--- a/packages/mui-material/src/CssBaseline/CssBaseline.js
+++ b/packages/mui-material/src/CssBaseline/CssBaseline.js
@@ -11,7 +11,8 @@ export const html = (theme, enableColorScheme) => ({
boxSizing: 'border-box',
// Fix font resize problem in iOS
WebkitTextSizeAdjust: '100%',
- ...(enableColorScheme && { colorScheme: theme.palette.mode }),
+ // When used under CssVarsProvider, colorScheme should not be applied dynamically because it will generate the stylesheet twice for server-rendered applications.
+ ...(enableColorScheme && !theme.vars && { colorScheme: theme.palette.mode }),
});
export const body = (theme) => ({
@@ -25,6 +26,14 @@ export const body = (theme) => ({
});
export const styles = (theme, enableColorScheme = false) => {
+ const colorSchemeStyles = {};
+ if (enableColorScheme && theme.colorSchemes) {
+ Object.entries(theme.colorSchemes).forEach(([key, scheme]) => {
+ colorSchemeStyles[theme.getColorSchemeSelector(key).replace(/\s*&/, '')] = {
+ colorScheme: scheme.palette?.mode,
+ };
+ });
+ }
let defaultStyles = {
html: html(theme, enableColorScheme),
'*, *::before, *::after': {
@@ -42,6 +51,7 @@ export const styles = (theme, enableColorScheme = false) => {
backgroundColor: (theme.vars || theme).palette.background.default,
},
},
+ ...colorSchemeStyles,
};
const themeOverrides = theme.components?.MuiCssBaseline?.styleOverrides;
diff --git a/packages/mui-material/src/ScopedCssBaseline/ScopedCssBaseline.js b/packages/mui-material/src/ScopedCssBaseline/ScopedCssBaseline.js
index 6ae0f1783954ab..f74c229df06bf9 100644
--- a/packages/mui-material/src/ScopedCssBaseline/ScopedCssBaseline.js
+++ b/packages/mui-material/src/ScopedCssBaseline/ScopedCssBaseline.js
@@ -22,6 +22,14 @@ const ScopedCssBaselineRoot = styled('div', {
slot: 'Root',
overridesResolver: (props, styles) => styles.root,
})(({ theme, ownerState }) => {
+ const colorSchemeStyles = {};
+ if (ownerState.enableColorScheme && theme.colorSchemes) {
+ Object.entries(theme.colorSchemes).forEach(([key, scheme]) => {
+ colorSchemeStyles[`&${theme.getColorSchemeSelector(key).replace(/\s*&/, '')}`] = {
+ colorScheme: scheme.palette?.mode,
+ };
+ });
+ }
return {
...html(theme, ownerState.enableColorScheme),
...body(theme),
@@ -31,6 +39,7 @@ const ScopedCssBaselineRoot = styled('div', {
'& strong, & b': {
fontWeight: theme.typography.fontWeightBold,
},
+ ...colorSchemeStyles,
};
});
diff --git a/packages/mui-material/src/styles/experimental_extendTheme.d.ts b/packages/mui-material/src/styles/experimental_extendTheme.d.ts
index 5ae0ea1cda08e7..fb2ceb05203afc 100644
--- a/packages/mui-material/src/styles/experimental_extendTheme.d.ts
+++ b/packages/mui-material/src/styles/experimental_extendTheme.d.ts
@@ -193,7 +193,7 @@ export interface PaletteTooltip {
// The Palette should be sync with `../themeCssVarsAugmentation/index.d.ts`
export interface ColorSystemOptions {
- palette?: Omit & {
+ palette?: PaletteOptions & {
common?: Partial;
primary?: Partial;
secondary?: Partial;
diff --git a/packages/mui-system/src/cssVars/createCssVarsProvider.d.ts b/packages/mui-system/src/cssVars/createCssVarsProvider.d.ts
index 75b04405daf9fa..808657beebdda9 100644
--- a/packages/mui-system/src/cssVars/createCssVarsProvider.d.ts
+++ b/packages/mui-system/src/cssVars/createCssVarsProvider.d.ts
@@ -39,11 +39,6 @@ export interface CssVarsProviderConfig {
* @default false
*/
disableTransitionOnChange?: boolean;
- /**
- * Indicate to the browser which color scheme is used (light or dark) for rendering built-in UI
- * @default true
- */
- enableColorScheme?: boolean;
/**
* A function to determine if the key, value should be attached as CSS Variable
* `keys` is an array that represents the object path keys.
diff --git a/packages/mui-system/src/cssVars/createCssVarsProvider.js b/packages/mui-system/src/cssVars/createCssVarsProvider.js
index 9e86d979596bb2..a867989af5e2e7 100644
--- a/packages/mui-system/src/cssVars/createCssVarsProvider.js
+++ b/packages/mui-system/src/cssVars/createCssVarsProvider.js
@@ -1,7 +1,7 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import MuiError from '@mui/utils/macros/MuiError.macro';
-import { deepmerge, unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils';
+import { deepmerge } from '@mui/utils';
import { GlobalStyles } from '@mui/styled-engine';
import cssVarsParser from './cssVarsParser';
import ThemeProvider from '../ThemeProvider';
@@ -24,7 +24,6 @@ export default function createCssVarsProvider(options) {
defaultMode: designSystemMode = 'light',
defaultColorScheme: designSystemColorScheme,
disableTransitionOnChange: designSystemTransitionOnChange = false,
- enableColorScheme: designSystemEnableColorScheme = true,
shouldSkipGeneratingVar: designSystemShouldSkipGeneratingVar,
resolveTheme,
excludeVariablesFromRoot,
@@ -60,7 +59,6 @@ export default function createCssVarsProvider(options) {
defaultMode = designSystemMode,
defaultColorScheme = designSystemColorScheme,
disableTransitionOnChange = designSystemTransitionOnChange,
- enableColorScheme = designSystemEnableColorScheme,
storageWindow = typeof window === 'undefined' ? undefined : window,
documentNode = typeof document === 'undefined' ? undefined : document,
colorSchemeNode = typeof document === 'undefined' ? undefined : document.documentElement,
@@ -75,6 +73,8 @@ export default function createCssVarsProvider(options) {
typeof defaultColorScheme === 'string' ? defaultColorScheme : defaultColorScheme.light;
const defaultDarkColorScheme =
typeof defaultColorScheme === 'string' ? defaultColorScheme : defaultColorScheme.dark;
+
+ // 1. Get the data about the `mode`, `colorScheme`, and setter functions.
const {
mode,
setMode,
@@ -92,29 +92,38 @@ export default function createCssVarsProvider(options) {
defaultMode,
storageWindow,
});
- const resolvedColorScheme = (() => {
+
+ const calculatedMode = (() => {
+ if (!mode) {
+ // This scope occurs on the server
+ if (defaultMode === 'system') {
+ return designSystemMode;
+ }
+ return defaultMode;
+ }
+ return mode;
+ })();
+ const calculatedColorScheme = (() => {
if (!colorScheme) {
// This scope occurs on the server
- if (defaultMode === 'dark') {
+ if (calculatedMode === 'dark') {
return defaultDarkColorScheme;
}
- // use light color scheme, if default mode is 'light' | 'auto'
+ // use light color scheme, if default mode is 'light' | 'system'
return defaultLightColorScheme;
}
return colorScheme;
})();
- let theme = restThemeProp;
+ // 2. Create CSS variables and store them in objects (to be generated in stylesheets in the final step)
const {
css: rootCss,
vars: rootVars,
parsedTheme,
- } = cssVarsParser(theme, {
- prefix: cssVarPrefix,
- shouldSkipGeneratingVar,
- });
+ } = cssVarsParser(restThemeProp, { prefix: cssVarPrefix, shouldSkipGeneratingVar });
- theme = {
+ // 3. Start composing the theme object
+ let theme = {
...parsedTheme,
components,
colorSchemes,
@@ -123,9 +132,11 @@ export default function createCssVarsProvider(options) {
getColorSchemeSelector: (targetColorScheme) => `[${attribute}="${targetColorScheme}"] &`,
};
+ // 4. Create color CSS variables and store them in objects (to be generated in stylesheets in the final step)
+ // The default color scheme stylesheet is constructed to have the least CSS specificity.
+ // The other color schemes uses selector, default as data attribute, to increase the CSS specificity so that they can override the default color scheme stylesheet.
const defaultColorSchemeStyleSheet = {};
const otherColorSchemesStyleSheet = {};
-
Object.entries(colorSchemes).forEach(([key, scheme]) => {
const {
css,
@@ -136,15 +147,11 @@ export default function createCssVarsProvider(options) {
shouldSkipGeneratingVar,
});
theme.vars = deepmerge(theme.vars, vars);
- if (key === resolvedColorScheme) {
- theme = {
- ...theme,
- ...parsedScheme,
- };
+ if (key === calculatedColorScheme) {
+ // 4.1 Merge the selected color scheme to the theme
+ theme = { ...theme, ...parsedScheme };
if (theme.palette) {
- // assign runtime mode & colorScheme
- theme.palette.mode = mode;
- theme.palette.colorScheme = resolvedColorScheme;
+ theme.palette.colorScheme = key;
}
}
const resolvedDefaultColorScheme = (() => {
@@ -173,6 +180,8 @@ export default function createCssVarsProvider(options) {
}
});
+ // 5. Declaring effects
+ // 5.1 Updates the selector value to use the current color scheme which tells CSS to use the proper stylesheet.
React.useEffect(() => {
if (colorScheme && colorSchemeNode) {
// attaches attribute to because the css variables are attached to :root (html)
@@ -180,27 +189,11 @@ export default function createCssVarsProvider(options) {
}
}, [colorScheme, attribute, colorSchemeNode]);
- useEnhancedEffect(() => {
- if (!mode || !enableColorScheme || !colorSchemeNode) {
- return undefined;
- }
- const priorColorScheme = colorSchemeNode.style.getPropertyValue('color-scheme');
- // `color-scheme` tells browser to render built-in elements according to its value: `light` or `dark`
- if (mode === 'system') {
- colorSchemeNode.style.setProperty('color-scheme', systemMode);
- } else {
- colorSchemeNode.style.setProperty('color-scheme', mode);
- }
-
- return () => {
- colorSchemeNode.style.setProperty('color-scheme', priorColorScheme);
- };
- }, [mode, systemMode, enableColorScheme, colorSchemeNode]);
-
+ // 5.2 Remove the CSS transition when color scheme changes to create instant experience.
+ // credit: https://github.com/pacocoursey/next-themes/blob/b5c2bad50de2d61ad7b52a9c5cdc801a78507d7a/index.tsx#L313
React.useEffect(() => {
let timer;
if (disableTransitionOnChange && hasMounted.current && documentNode) {
- // credit: https://github.com/pacocoursey/next-themes/blob/b5c2bad50de2d61ad7b52a9c5cdc801a78507d7a/index.tsx#L313
const css = documentNode.createElement('style');
css.appendChild(documentNode.createTextNode(DISABLE_CSS_TRANSITION));
documentNode.head.appendChild(css);
@@ -216,7 +209,6 @@ export default function createCssVarsProvider(options) {
clearTimeout(timer);
};
}, [colorScheme, disableTransitionOnChange, documentNode]);
-
React.useEffect(() => {
hasMounted.current = true;
return () => {
@@ -228,6 +220,7 @@ export default function createCssVarsProvider(options) {
systemGetInitColorSchemeScript({
attribute: defaultAttribute,
colorSchemeStorageKey: defaultColorSchemeStorageKey,
+ defaultMode: designSystemMode,
+ defaultLightColorScheme,
+ defaultDarkColorScheme,
modeStorageKey: defaultModeStorageKey,
- enableColorScheme: designSystemEnableColorScheme,
...params,
});
diff --git a/packages/mui-system/src/cssVars/createCssVarsProvider.test.js b/packages/mui-system/src/cssVars/createCssVarsProvider.test.js
index 8002df94e874fe..5ff48e456d8c25 100644
--- a/packages/mui-system/src/cssVars/createCssVarsProvider.test.js
+++ b/packages/mui-system/src/cssVars/createCssVarsProvider.test.js
@@ -15,7 +15,6 @@ describe('createCssVarsProvider', () => {
addListener: () => {},
removeListener: () => {},
});
- let shouldSupportColorScheme;
beforeEach(() => {
originalMatchmedia = window.matchMedia;
@@ -34,11 +33,6 @@ describe('createCssVarsProvider', () => {
// clear the localstorage
storage = {};
window.matchMedia = createMatchMedia(false);
-
- // Currently supported Firefox does not support `color-scheme`.
- // Instead of skipping relevant tests entirely we assert that they work differently in Firefox.
- // This ensures that we're automatically notified once we remove older Firefox versions from the support matrix.
- shouldSupportColorScheme = !/Firefox/.test(navigator.userAgent);
});
afterEach(() => {
window.matchMedia = originalMatchmedia;
@@ -249,109 +243,6 @@ describe('createCssVarsProvider', () => {
expect(screen.getByText('var(--palette-grey)')).not.to.equal(null);
});
- describe('[option]: `enableColorScheme`', () => {
- it('set `color-scheme` property on with correct mode, given `enableColorScheme` is true and `mode` is `light` or `dark`', () => {
- const { CssVarsProvider, useColorScheme } = createCssVarsProvider({
- theme: {
- colorSchemes: { light: {}, dark: {} },
- },
- defaultColorScheme: 'light',
- enableColorScheme: true,
- });
- const Consumer = () => {
- const { setMode } = useColorScheme();
- return ;
- };
- render(
-
-
- ,
- );
- expect(document.documentElement).toHaveComputedStyle({
- colorScheme: shouldSupportColorScheme ? 'light' : '',
- });
-
- fireEvent.click(screen.getByRole('button', { name: 'change to dark' }));
-
- expect(document.documentElement).toHaveComputedStyle({
- colorScheme: shouldSupportColorScheme ? 'dark' : '',
- });
- });
-
- it('set `color-scheme` property on with correct mode, given `enableColorScheme` is true and mode is `system`', () => {
- window.matchMedia = createMatchMedia(true); // system matches 'prefers-color-scheme: dark'
-
- const { CssVarsProvider, useColorScheme } = createCssVarsProvider({
- theme: {
- colorSchemes: { light: {}, dark: {} },
- },
- defaultColorScheme: 'light',
- enableColorScheme: true,
- });
- const Consumer = () => {
- const { setMode } = useColorScheme();
- return ;
- };
- render(
-
-
- ,
- );
- expect(document.documentElement).toHaveComputedStyle({
- colorScheme: shouldSupportColorScheme ? 'light' : '',
- });
-
- fireEvent.click(screen.getByRole('button', { name: 'change to system' }));
-
- expect(document.documentElement).toHaveComputedStyle({
- colorScheme: shouldSupportColorScheme ? 'dark' : '',
- });
- });
-
- it('does not set `color-scheme` property on with correct mode, given`enableColorScheme` is false', () => {
- const currentColorScheme = window
- .getComputedStyle(document.documentElement)
- .getPropertyValue('color-scheme');
- const { CssVarsProvider } = createCssVarsProvider({
- theme: {
- colorSchemes: { light: {}, dark: {} },
- },
- defaultColorScheme: 'light',
- enableColorScheme: false,
- });
- const Consumer = () => ;
-
- render(
-
-
- ,
- );
- expect(document.documentElement).toHaveComputedStyle({
- colorScheme: shouldSupportColorScheme ? currentColorScheme : '',
- });
- });
-
- it('cleans up `color-scheme` property on , given`enableColorScheme` is true', () => {
- const previousColorScheme = window
- .getComputedStyle(document.documentElement)
- .getPropertyValue('color-scheme');
- const { CssVarsProvider } = createCssVarsProvider({
- theme: {
- colorSchemes: { light: {}, dark: {} },
- },
- defaultColorScheme: 'light',
- enableColorScheme: true,
- });
- const { unmount } = render();
-
- unmount();
-
- expect(document.documentElement).toHaveComputedStyle({
- colorScheme: previousColorScheme,
- });
- });
- });
-
describe('[option]: `disableTransitionOnChange`', () => {
clock.withFakeTimers();
it('disable all css transitions when switching bewteen modes, given `disableTransitionOnChange` is true', () => {
diff --git a/packages/mui-system/src/cssVars/getInitColorSchemeScript.tsx b/packages/mui-system/src/cssVars/getInitColorSchemeScript.tsx
index 8c4ac844b456c4..ee5c582bf1082d 100644
--- a/packages/mui-system/src/cssVars/getInitColorSchemeScript.tsx
+++ b/packages/mui-system/src/cssVars/getInitColorSchemeScript.tsx
@@ -5,11 +5,6 @@ export const DEFAULT_COLOR_SCHEME_STORAGE_KEY = 'color-scheme';
export const DEFAULT_ATTRIBUTE = 'data-color-scheme';
export interface GetInitColorSchemeScriptOptions {
- /**
- * Indicate to the browser which color scheme is used (light or dark) for rendering built-in UI
- * @default true
- */
- enableColorScheme?: boolean;
/**
* The mode to be used for the first visit
* @default 'light'
@@ -49,7 +44,6 @@ export interface GetInitColorSchemeScriptOptions {
export default function getInitColorSchemeScript(options?: GetInitColorSchemeScriptOptions) {
const {
- enableColorScheme = true,
defaultMode = 'light',
defaultLightColorScheme = 'light',
defaultDarkColorScheme = 'dark',
@@ -86,9 +80,6 @@ export default function getInitColorSchemeScript(options?: GetInitColorSchemeScr
if (colorScheme) {
${colorSchemeNode}.setAttribute('${attribute}', colorScheme);
}
- if (${enableColorScheme} && !!cssColorScheme) {
- ${colorSchemeNode}.style.setProperty('color-scheme', cssColorScheme);
- }
} catch (e) {} })();`,
}}
/>
diff --git a/test/regressions/fixtures/CssBaseline/JoyCssBaseline.js b/test/regressions/fixtures/CssBaseline/JoyCssBaseline.js
new file mode 100644
index 00000000000000..3c02b8620e2680
--- /dev/null
+++ b/test/regressions/fixtures/CssBaseline/JoyCssBaseline.js
@@ -0,0 +1,25 @@
+import * as React from 'react';
+import { CssVarsProvider } from '@mui/joy/styles';
+import Box from '@mui/joy/Box';
+import CssBaseline from '@mui/joy/CssBaseline';
+
+export default function JoyCssBaseline() {
+ return (
+
+
+
+
+ {/* The scrollbar should be light */}
+
+
+
+ {/* The scrollbar should be dark */}
+
+
+
+
+ );
+}
diff --git a/test/regressions/fixtures/CssBaseline/JoyScopedCssBaseline.js b/test/regressions/fixtures/CssBaseline/JoyScopedCssBaseline.js
new file mode 100644
index 00000000000000..60ee6cc8a6f255
--- /dev/null
+++ b/test/regressions/fixtures/CssBaseline/JoyScopedCssBaseline.js
@@ -0,0 +1,32 @@
+import * as React from 'react';
+import { CssVarsProvider, extendTheme } from '@mui/joy/styles';
+import colors from '@mui/joy/colors';
+import Box from '@mui/joy/Box';
+import ScopedCssBaseline from '@mui/joy/ScopedCssBaseline';
+
+const theme = extendTheme({
+ colorSchemes: {
+ forest: {
+ palette: {
+ mode: 'dark',
+ background: {
+ body: colors.green[200],
+ },
+ },
+ },
+ },
+});
+
+export default function JoyScopedCssBaseline() {
+ return (
+
+
+ {/* The scrollbar should be dark */}
+
+
+
+ );
+}
diff --git a/test/regressions/fixtures/CssBaseline/MaterialCssBaseline.js b/test/regressions/fixtures/CssBaseline/MaterialCssBaseline.js
new file mode 100644
index 00000000000000..56e5b874851d5c
--- /dev/null
+++ b/test/regressions/fixtures/CssBaseline/MaterialCssBaseline.js
@@ -0,0 +1,25 @@
+import * as React from 'react';
+import { Experimental_CssVarsProvider as CssVarsProvider } from '@mui/material/styles';
+import Box from '@mui/material/Box';
+import CssBaseline from '@mui/material/CssBaseline';
+
+export default function MaterialCssBaseline() {
+ return (
+
+
+
+
+ {/* The scrollbar should be light */}
+
+
+
+ {/* The scrollbar should be dark */}
+
+
+
+
+ );
+}
diff --git a/test/regressions/fixtures/CssBaseline/MaterialScopedCssBaseline.js b/test/regressions/fixtures/CssBaseline/MaterialScopedCssBaseline.js
new file mode 100644
index 00000000000000..00aed3b0ec229d
--- /dev/null
+++ b/test/regressions/fixtures/CssBaseline/MaterialScopedCssBaseline.js
@@ -0,0 +1,41 @@
+import * as React from 'react';
+import {
+ Experimental_CssVarsProvider as CssVarsProvider,
+ experimental_extendTheme as extendTheme,
+ createTheme,
+} from '@mui/material/styles';
+import { cyan } from '@mui/material/colors';
+import Box from '@mui/material/Box';
+import ScopedCssBaseline from '@mui/material/ScopedCssBaseline';
+
+const ocean = createTheme({
+ palette: {
+ mode: 'dark',
+ background: {
+ paper: cyan[200],
+ },
+ },
+});
+
+const theme = extendTheme({
+ colorSchemes: {
+ ocean: {
+ palette: ocean.palette,
+ },
+ },
+});
+
+export default function MaterialScopedCssBaseline() {
+ return (
+
+
+ {/* The scrollbar should be dark */}
+
+
+
+ );
+}