Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[blog] Fix dark mode support
Browse files Browse the repository at this point in the history
oliviertassinari committed Jan 28, 2023

Unverified

This user has not yet uploaded their public signing key.
1 parent 0d26f5c commit 38ae20e
Showing 4 changed files with 47 additions and 56 deletions.
2 changes: 1 addition & 1 deletion docs/src/modules/components/SkipLink.tsx
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ import { useTranslate } from 'docs/src/modules/utils/i18n';
const StyledLink = styled(MuiLink)(({ theme }) => ({
position: 'fixed',
padding: theme.spacing(1),
background: theme.palette.background.paper,
background: (theme.vars || theme).palette.background.paper,
transition: theme.transitions.create('top', {
easing: theme.transitions.easing.easeIn,
duration: theme.transitions.duration.leavingScreen,
59 changes: 25 additions & 34 deletions docs/src/modules/components/ThemeContext.js
Original file line number Diff line number Diff line change
@@ -13,7 +13,6 @@ import {
getThemedComponents,
getMetaThemeColor,
} from 'docs/src/modules/brandingTheme';
import PageContext from './PageContext';

const languageMap = {
en: enUS,
@@ -109,11 +108,8 @@ if (process.env.NODE_ENV !== 'production') {

export function ThemeProvider(props) {
const { children } = props;
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const pageContextValue = React.useContext(PageContext);
// `activePage` does not exist for playground pages
// forcing light mode in playground avoids the need for a wrapping theme in playground pages
const preferredMode = pageContextValue.activePage && prefersDarkMode ? 'dark' : 'light';
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)', { noSsr: true });
const preferredMode = prefersDarkMode ? 'dark' : 'light';

const [themeOptions, dispatch] = React.useReducer(
(state, action) => {
@@ -162,34 +158,42 @@ export function ThemeProvider(props) {
throw new Error(`Unrecognized type ${action.type}`);
}
},
{ ...themeInitialOptions, paletteMode: preferredMode },
{ ...themeInitialOptions, paletteMode: 'light' },
);

const userLanguage = useUserLanguage();
const { dense, direction, paletteColors, paletteMode, spacing } = themeOptions;

useLazyCSS('/static/styles/prism-okaidia.css', '#prismjs');

React.useEffect(() => {
if (typeof window !== 'undefined') {
const nextPaletteColors = JSON.parse(getCookie('paletteColors') || 'null');
let nextPaletteMode = localStorage.getItem('mui-mode') || preferredMode; // syncing with homepage, can be removed once all pages are migrated to CSS variables
if (nextPaletteMode === 'system') {
nextPaletteMode = preferredMode;
}
useEnhancedEffect(() => {
const nextPaletteColors = JSON.parse(getCookie('paletteColors') || 'null');

dispatch({
type: 'CHANGE',
payload: { paletteColors: nextPaletteColors, paletteMode: nextPaletteMode },
});
let nextPaletteMode = localStorage.getItem('mui-mode') || preferredMode; // syncing with homepage, can be removed once all pages are migrated to CSS variables
if (nextPaletteMode === 'system') {
nextPaletteMode = preferredMode;
}

dispatch({
type: 'CHANGE',
payload: { paletteColors: nextPaletteColors, paletteMode: nextPaletteMode },
});
}, [preferredMode]);

useEnhancedEffect(() => {
document.body.dir = direction;
}, [direction]);

React.useEffect(() => {
useEnhancedEffect(() => {
// To support light and dark mode images in the docs
if (paletteMode === 'dark') {
document.body.classList.remove('mode-light');
document.body.classList.add('mode-dark');
} else {
document.body.classList.remove('mode-dark');
document.body.classList.add('mode-light');
}

const metas = document.querySelectorAll('meta[name="theme-color"]');
metas.forEach((meta) => {
meta.setAttribute('content', getMetaThemeColor(paletteMode));
@@ -238,23 +242,10 @@ export function ThemeProvider(props) {

React.useEffect(() => {
// Expose the theme as a global variable so people can play with it.
if (typeof window !== 'undefined') {
window.theme = theme;
window.createTheme = createTheme;
}
window.theme = theme;
window.createTheme = createTheme;
}, [theme]);

useEnhancedEffect(() => {
// To support light and dark mode images in the docs
if (theme.palette.mode === 'dark') {
document.body.classList.remove('mode-light');
document.body.classList.add('mode-dark');
} else {
document.body.classList.remove('mode-dark');
document.body.classList.add('mode-light');
}
}, [theme.palette.mode]);

return (
<MuiThemeProvider theme={theme}>
<DispatchContext.Provider value={dispatch}>{children}</DispatchContext.Provider>
28 changes: 14 additions & 14 deletions packages/mui-material/src/useMediaQuery/useMediaQuery.ts
Original file line number Diff line number Diff line change
@@ -30,7 +30,6 @@ export interface Options {
* This option is kept for backwards compatibility and has no longer any effect.
* It's previous behavior is now handled automatically.
*/
// TODO: Deprecate for v6
noSsr?: boolean;
ssrMatchMedia?: (query: string) => { matches: boolean };
}
@@ -42,11 +41,8 @@ function useMediaQueryOld(
ssrMatchMedia: ((query: string) => { matches: boolean }) | null,
noSsr: boolean | undefined,
): boolean {
const supportMatchMedia =
typeof window !== 'undefined' && typeof window.matchMedia !== 'undefined';

const [match, setMatch] = React.useState(() => {
if (noSsr && supportMatchMedia) {
if (noSsr && matchMedia) {
return matchMedia!(query).matches;
}
if (ssrMatchMedia) {
@@ -61,7 +57,7 @@ function useMediaQueryOld(
useEnhancedEffect(() => {
let active = true;

if (!supportMatchMedia) {
if (!matchMedia) {
return undefined;
}

@@ -81,7 +77,7 @@ function useMediaQueryOld(
active = false;
queryList.removeListener(updateMatch);
};
}, [query, matchMedia, supportMatchMedia]);
}, [query, matchMedia]);

return match;
}
@@ -94,15 +90,9 @@ function useMediaQueryNew(
defaultMatches: boolean,
matchMedia: typeof window.matchMedia | null,
ssrMatchMedia: ((query: string) => { matches: boolean }) | null,
noSsr: boolean | undefined,
): boolean {
const getDefaultSnapshot = React.useCallback(() => defaultMatches, [defaultMatches]);
const getServerSnapshot = React.useMemo(() => {
if (ssrMatchMedia !== null) {
const { matches } = ssrMatchMedia(query);
return () => matches;
}
return getDefaultSnapshot;
}, [getDefaultSnapshot, query, ssrMatchMedia]);
const [getSnapshot, subscribe] = React.useMemo(() => {
if (matchMedia === null) {
return [getDefaultSnapshot, () => () => {}];
@@ -121,6 +111,16 @@ function useMediaQueryNew(
},
];
}, [getDefaultSnapshot, matchMedia, query]);
const getServerSnapshot = React.useMemo(() => {
if (noSsr && matchMedia) {
return () => matchMedia!(query).matches;
}
if (ssrMatchMedia !== null) {
const { matches } = ssrMatchMedia(query);
return () => matches;
}
return getDefaultSnapshot;
}, [noSsr, matchMedia, getDefaultSnapshot, query, ssrMatchMedia]);
const match = maybeReactUseSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);

return match;
14 changes: 7 additions & 7 deletions packages/mui-system/src/cssVars/createCssVarsProvider.js
Original file line number Diff line number Diff line change
@@ -108,14 +108,14 @@ export default function createCssVarsProvider(options) {
}

const calculatedMode = (() => {
if (!mode) {
// This scope occurs on the server
if (defaultMode === 'system') {
return designSystemMode;
}
return defaultMode;
if (mode) {
return mode;
}
// This scope occurs on the server
if (defaultMode === 'system') {
return designSystemMode;
}
return mode;
return defaultMode;
})();
const calculatedColorScheme = (() => {
if (!colorScheme) {

0 comments on commit 38ae20e

Please sign in to comment.