Skip to content

Commit

Permalink
[blog] Fix dark mode support
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari committed Jan 28, 2023
1 parent 0d26f5c commit a7c7c1c
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 50 deletions.
2 changes: 1 addition & 1 deletion docs/src/modules/components/SkipLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
59 changes: 25 additions & 34 deletions docs/src/modules/components/ThemeContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
getThemedComponents,
getMetaThemeColor,
} from 'docs/src/modules/brandingTheme';
import PageContext from './PageContext';

const languageMap = {
en: enUS,
Expand Down Expand Up @@ -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) => {
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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>
Expand Down
16 changes: 8 additions & 8 deletions packages/mui-material/src/useMediaQuery/useMediaQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
}
Expand All @@ -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) {
Expand All @@ -61,7 +57,7 @@ function useMediaQueryOld(
useEnhancedEffect(() => {
let active = true;

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

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

return match;
}
Expand All @@ -94,15 +90,19 @@ 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 (noSsr && matchMedia) {
return () => matchMedia!(query).matches;
}
if (ssrMatchMedia !== null) {
const { matches } = ssrMatchMedia(query);
return () => matches;
}
return getDefaultSnapshot;
}, [getDefaultSnapshot, query, ssrMatchMedia]);
}, [noSsr, matchMedia, getDefaultSnapshot, query, ssrMatchMedia]);
const [getSnapshot, subscribe] = React.useMemo(() => {
if (matchMedia === null) {
return [getDefaultSnapshot, () => () => {}];
Expand Down
14 changes: 7 additions & 7 deletions packages/mui-system/src/cssVars/createCssVarsProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit a7c7c1c

Please sign in to comment.