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

[system] Fix mode blink when open multiple sessions #33877

Merged
merged 10 commits into from Aug 24, 2022
Expand Up @@ -611,7 +611,6 @@ describe('createCssVarsProvider', () => {
);

expect(screen.getByTestId('current-mode').textContent).to.equal('dark');
expect(global.localStorage.setItem.calledWith(customModeStorageKey, 'dark')).to.equal(true);
Copy link
Member Author

Choose a reason for hiding this comment

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

This is not necessary because the value is already dark.

});

it('support custom storage window', () => {
Expand Down
35 changes: 16 additions & 19 deletions packages/mui-system/src/cssVars/useCurrentColorScheme.ts
Expand Up @@ -90,13 +90,17 @@ export function getColorScheme<SupportedColorScheme extends string>(
});
}

function resolveValue(key: string, defaultValue?: string) {
function initializeValue(key: string, defaultValue: string) {
if (typeof window === 'undefined') {
return undefined;
}
let value;
try {
value = localStorage.getItem(key) || undefined;
if (!value) {
// the first time that user enters the site.
localStorage.setItem(key, defaultValue);
}
} catch (e) {
// Unsupported
}
Expand Down Expand Up @@ -129,12 +133,20 @@ export default function useCurrentColorScheme<SupportedColorScheme extends strin
const joinedColorSchemes = supportedColorSchemes.join(',');

const [state, setState] = React.useState(() => {
const initialMode = resolveValue(modeStorageKey, defaultMode);
const initialMode = initializeValue(modeStorageKey, defaultMode);
const lightColorScheme = initializeValue(
`${colorSchemeStorageKey}-light`,
defaultLightColorScheme,
);
const darkColorScheme = initializeValue(
`${colorSchemeStorageKey}-dark`,
defaultDarkColorScheme,
);
return {
mode: initialMode,
systemMode: getSystemMode(initialMode),
lightColorScheme: resolveValue(`${colorSchemeStorageKey}-light`) || defaultLightColorScheme,
darkColorScheme: resolveValue(`${colorSchemeStorageKey}-dark`) || defaultDarkColorScheme,
lightColorScheme,
darkColorScheme,
} as State<SupportedColorScheme>;
});

Expand Down Expand Up @@ -243,21 +255,6 @@ export default function useCurrentColorScheme<SupportedColorScheme extends strin
return () => media.removeListener(handler);
}, []);

// Save mode, lightColorScheme & darkColorScheme to localStorage
React.useEffect(() => {
siriwatknp marked this conversation as resolved.
Show resolved Hide resolved
if (state.mode) {
localStorage.setItem(modeStorageKey, state.mode);
}
processState(state, (mode) => {
if (mode === 'light') {
localStorage.setItem(`${colorSchemeStorageKey}-light`, state.lightColorScheme);
}
if (mode === 'dark') {
localStorage.setItem(`${colorSchemeStorageKey}-dark`, state.darkColorScheme);
}
});
}, [state, colorSchemeStorageKey, modeStorageKey]);

// Handle when localStorage has changed
React.useEffect(() => {
const handleStorage = (event: StorageEvent) => {
Expand Down
Expand Up @@ -15,12 +15,13 @@ const { CssVarsProvider } = createCssVarsProvider({
},
defaultColorScheme: {
light: 'light',
dark: 'dark',
},
});

export default function DarkModeSpecificity() {
export default function ColorSchemeSelector() {
return (
<CssVarsProvider modeStorageKey="dark-mode-specificity">
Copy link
Member Author

Choose a reason for hiding this comment

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

no need to use a custom key because the storage is cleared between tests in test/regressions/index.test.js

<CssVarsProvider>
<Box
sx={(theme) => ({
p: 2,
Expand Down
Expand Up @@ -33,7 +33,7 @@ const DarkMode = () => {

export default function DarkModeSpecificity() {
return (
<CssVarsProvider modeStorageKey="dark-mode-specificity">
<CssVarsProvider>
<DarkMode />
<div style={{ background: 'var(--background-default)', color: '#888', padding: '1rem' }}>
Background should be #000.
Expand Down
Expand Up @@ -22,9 +22,9 @@ const { CssVarsProvider } = createCssVarsProvider({
},
});

export default function DarkModeSpecificity() {
export default function ForceColorSchemes() {
return (
<CssVarsProvider modeStorageKey="force-color-schemes">
<CssVarsProvider>
<div
data-color-scheme="dark"
style={{
Expand Down
6 changes: 6 additions & 0 deletions test/regressions/index.test.js
Expand Up @@ -77,6 +77,12 @@ async function main() {
await fse.emptyDir(screenshotDir);

describe('visual regressions', () => {
beforeEach(async () => {
await page.evaluate(() => {
localStorage.clear();
});
});

after(async () => {
await browser.close();
});
Expand Down