Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CssVarsProvider][Material UI] Exclude dark mode variables from :root stylesheet #34131

Merged
merged 11 commits into from Sep 22, 2022
2 changes: 2 additions & 0 deletions packages/mui-material/src/styles/CssVarsProvider.tsx
@@ -1,6 +1,7 @@
import { unstable_createCssVarsProvider as createCssVarsProvider } from '@mui/system';
import experimental_extendTheme, { SupportedColorScheme } from './experimental_extendTheme';
import createTypography from './createTypography';
import excludeVariablesFromRoot from './excludeVariablesFromRoot';

const shouldSkipGeneratingVar = (keys: string[]) =>
!!keys[0].match(/(typography|mixins|breakpoints|direction|transitions)/) ||
Expand All @@ -27,6 +28,7 @@ const { CssVarsProvider, useColorScheme, getInitColorSchemeScript } =
return newTheme;
},
shouldSkipGeneratingVar,
excludeVariablesFromRoot,
});

export {
Expand Down
24 changes: 24 additions & 0 deletions packages/mui-material/src/styles/excludeVariablesFromRoot.test.ts
@@ -0,0 +1,24 @@
import { expect } from 'chai';
import excludeVariablesFromRoot from './excludeVariablesFromRoot';

describe('excludeVariablesFromRoot', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add test in the CssVarsProvider about this logic? Also, how do we make sure we remove the variables only in light mode? Adding tests for both cases would be great.

I would argue that the alternative approach is easier to learn and apply rather than adding new API, and at this moment bundle size doesn't really concerns me that much.

Copy link
Member Author

@siriwatknp siriwatknp Sep 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add test in the CssVarsProvider about this logic? Also, how do we make sure we remove the variables only in light mode? Adding tests for both cases would be great.

Added 2 regression tests

  • Test the default dark mode to ensure that the variables exist in dark mode.
  • The default mode is dark and then switches to light to ensure that those variables does not exist in light mode.

I would argue that the alternative approach is easier to learn and apply rather than adding new API, and at this moment bundle size doesn't really concerns me that much.

It might create confusion for developers and be prone to errors:

  • Introducing the unknown variables (do we need to discuss the name?)
  • Need to document the unknown variables
  • Developer could accidentally remove the variables in the light mode which will cause unexpected result.
  • Bundle size will grow if you have more than light and `dark.

I rather have this done internally, so developers do not need to worry about these edge cases.

it('should return true', () => {
[...Array(25)].forEach((_, index) => {
if (index !== 0) {
expect(excludeVariablesFromRoot(`--mui-overlays-${index}`)).to.equal(true);
}
});
expect(excludeVariablesFromRoot(`--mui-palette-AppBar-darkBg`)).to.equal(true);
expect(excludeVariablesFromRoot(`--mui-palette-AppBar-darkColor`)).to.equal(true);
});

it('should return true for custom prefix', () => {
[...Array(25)].forEach((_, index) => {
if (index !== 0) {
expect(excludeVariablesFromRoot(`--foo-bar-overlays-${index}`)).to.equal(true);
}
});
expect(excludeVariablesFromRoot(`--foo-bar-palette-AppBar-darkBg`)).to.equal(true);
expect(excludeVariablesFromRoot(`--foo-bar-palette-AppBar-darkColor`)).to.equal(true);
});
});
7 changes: 7 additions & 0 deletions packages/mui-material/src/styles/excludeVariablesFromRoot.ts
@@ -0,0 +1,7 @@
/**
* @internal These variables should not appear in the :root stylesheet when the `defaultMode="dark"`
*/
const excludeVariablesFromRoot = (cssVar: string) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wondering if people will ever need this as feature on their side. If yes, we could export this so that they can extend/override it.

!!cssVar.match(/(overlays-[0-9]|palette-AppBar-darkBg|palette-AppBar-darkColor)/);

export default excludeVariablesFromRoot;
8 changes: 8 additions & 0 deletions packages/mui-system/src/cssVars/createCssVarsProvider.d.ts
Expand Up @@ -124,6 +124,14 @@ export default function createCssVarsProvider<ColorScheme extends string>(
* variants from those tokens.
*/
resolveTheme?: (theme: any) => any; // the type is any because it depends on the design system.
/**
* @internal
* If the function return `true`, the variable is excluded from the `colorSchemeSelector` (:root by default)
*
* Some variables are intended to be used in a specific color scheme only. They should be excluded when the default mode is set to the color scheme.
* This is introduced to fix https://github.com/mui/material-ui/issues/34084
*/
excludeVariablesFromRoot?: (cssVar: string) => boolean;
},
): CreateCssVarsProviderResult<ColorScheme>;

Expand Down
13 changes: 13 additions & 0 deletions packages/mui-system/src/cssVars/createCssVarsProvider.js
Expand Up @@ -27,6 +27,7 @@ export default function createCssVarsProvider(options) {
enableColorScheme: designSystemEnableColorScheme = true,
shouldSkipGeneratingVar: designSystemShouldSkipGeneratingVar,
resolveTheme,
excludeVariablesFromRoot,
} = options;

if (
Expand Down Expand Up @@ -156,7 +157,19 @@ export default function createCssVarsProvider(options) {
return defaultColorScheme.light;
})();
if (key === resolvedDefaultColorScheme) {
const excludedVariables = {};
siriwatknp marked this conversation as resolved.
Show resolved Hide resolved
if (excludeVariablesFromRoot) {
Object.keys(css).forEach((cssVar) => {
if (excludeVariablesFromRoot(cssVar)) {
excludedVariables[cssVar] = css[cssVar];
delete css[cssVar];
}
});
}
defaultColorSchemeStyleSheet[`${colorSchemeSelector}, [${attribute}="${key}"]`] = css;
if (excludeVariablesFromRoot) {
defaultColorSchemeStyleSheet[`[${attribute}="${key}"]`] = excludedVariables;
}
} else {
otherColorSchemesStyleSheet[
`${colorSchemeSelector === ':root' ? '' : colorSchemeSelector}[${attribute}="${key}"]`
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-system/src/cssVars/cssVarsParser.ts
Expand Up @@ -125,7 +125,7 @@ export default function cssVarsParser<T extends Record<string, any>>(
},
) {
const { prefix, shouldSkipGeneratingVar } = options || {};
const css = {} as NestedRecord<string>;
const css = {} as Record<string, string | number>;
const vars = {} as NestedRecord<string>;
const parsedTheme = {} as T;

Expand Down