diff --git a/packages/docusaurus-theme-common/src/contexts/colorMode.tsx b/packages/docusaurus-theme-common/src/contexts/colorMode.tsx index 4a2482f907..6f4def96b9 100644 --- a/packages/docusaurus-theme-common/src/contexts/colorMode.tsx +++ b/packages/docusaurus-theme-common/src/contexts/colorMode.tsx @@ -13,6 +13,7 @@ import React, { useMemo, type ReactNode, } from 'react'; +import useIsBrowser from '@docusaurus/useIsBrowser'; import {ReactContextError} from '../utils/reactUtils'; import {createStorageSlot} from '../utils/storageUtils'; import {useThemeConfig} from '../utils/useThemeConfig'; @@ -124,10 +125,17 @@ function useColorModeState() { const { colorMode: {defaultMode}, } = useThemeConfig(); + const isBrowser = useIsBrowser(); - const [colorMode, setColorModeState] = useState(defaultMode); - const [colorModeChoice, setColorModeChoiceState] = - useState(null); + // Since the provider may unmount/remount on client navigation, we need to + // reinitialize the state with the correct values to avoid visual glitches. + // See also https://github.com/facebook/docusaurus/issues/11399#issuecomment-3279181314 + const [colorMode, setColorModeState] = useState( + isBrowser ? ColorModeAttribute.get() : defaultMode, + ); + const [colorModeChoice, setColorModeChoiceState] = useState( + isBrowser ? ColorModeChoiceAttribute.get() : null, + ); useEffect(() => { setColorModeState(ColorModeAttribute.get());