fix(v2): Fix announcementBar layout shifts (#5040)

* Fix announcementBar layout shift

* useAnnouncementBar should return correct state after hydration

* refactor announcementBar => move utils to theme-common

* restore previous announcementBar

* typo
This commit is contained in:
Sébastien Lorber 2021-06-24 11:35:35 +02:00 committed by GitHub
parent 814455f88e
commit 9916a0b4a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 179 additions and 110 deletions

View file

@ -6,7 +6,7 @@
*/
import {DocusaurusContext, Plugin} from '@docusaurus/types';
import {ThemeConfig} from '@docusaurus/theme-common';
import type {ThemeConfig} from '@docusaurus/theme-common';
import {getTranslationFiles, translateThemeConfig} from './translations';
import path from 'path';
import Module from 'module';
@ -24,7 +24,7 @@ const ContextReplacementPlugin = requireFromDocusaurusCore(
// Need to be inlined to prevent dark mode FOUC
// Make sure that the 'storageKey' is the same as the one in `/theme/hooks/useTheme.js`
const storageKey = 'theme';
const ThemeStorageKey = 'theme';
const noFlashColorMode = ({defaultMode, respectPrefersColorScheme}) => {
return `(function() {
var defaultMode = '${defaultMode}';
@ -37,7 +37,7 @@ const noFlashColorMode = ({defaultMode, respectPrefersColorScheme}) => {
function getStoredTheme() {
var theme = null;
try {
theme = localStorage.getItem('${storageKey}');
theme = localStorage.getItem('${ThemeStorageKey}');
} catch (err) {}
return theme;
}
@ -63,6 +63,26 @@ const noFlashColorMode = ({defaultMode, respectPrefersColorScheme}) => {
})();`;
};
// Duplicated constant. Unfortunately we can't import it from theme-common, as we need to support older nodejs versions without ESM support
// TODO: import from theme-common once we only support Node.js with ESM support
// + move all those announcementBar stuff there too
export const AnnouncementBarDismissStorageKey =
'docusaurus.announcement.dismiss';
const AnnouncementBarDismissDataAttribute =
'data-announcement-bar-initially-dismissed';
// We always render the announcement bar html on the server, to prevent layout shifts on React hydration
// The theme can use CSS + the data attribute to hide the announcement bar asap (before React hydration)
const AnnouncementBarInlineJavaScript = `
(function() {
function isDismissed() {
try {
return localStorage.getItem('${AnnouncementBarDismissStorageKey}') === 'true';
} catch (err) {}
return false;
}
document.documentElement.setAttribute('${AnnouncementBarDismissDataAttribute}', isDismissed());
})();`;
function getInfimaCSSFile(direction) {
return `infima/dist/css/default/default${
direction === 'rtl' ? '-rtl' : ''
@ -82,7 +102,11 @@ export default function docusaurusThemeClassic(
i18n: {currentLocale, localeConfigs},
} = context;
const themeConfig = (roughlyTypedThemeConfig || {}) as ThemeConfig;
const {colorMode, prism: {additionalLanguages = []} = {}} = themeConfig;
const {
announcementBar,
colorMode,
prism: {additionalLanguages = []} = {},
} = themeConfig;
const {customCss} = options || {};
const {direction} = localeConfigs[currentLocale];
@ -178,7 +202,10 @@ export default function docusaurusThemeClassic(
preBodyTags: [
{
tagName: 'script',
innerHTML: noFlashColorMode(colorMode),
innerHTML: `
${noFlashColorMode(colorMode)}
${announcementBar ? AnnouncementBarInlineJavaScript : ''}
`,
},
],
};