diff --git a/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts b/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts index 06eaef6b3a..ba92ca4a1f 100644 --- a/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts +++ b/packages/docusaurus-theme-common/src/hooks/useWindowSize.ts @@ -17,15 +17,20 @@ const windowSizes = { type WindowSize = keyof typeof windowSizes; -const DesktopThresholdWidth = 996; +// Note: this value is also hardcoded in Infima +// Both JS and CSS must have the same value +// Updating this JS value alone is not enough +// See https://github.com/facebook/docusaurus/issues/9603 +const DesktopBreakpoint = 996; -function getWindowSize() { +function getWindowSize(desktopBreakpoint: number): WindowSize { if (!ExecutionEnvironment.canUseDOM) { throw new Error( 'getWindowSize() should only be called after React hydration', ); } - return window.innerWidth > DesktopThresholdWidth + + return window.innerWidth > desktopBreakpoint ? windowSizes.desktop : windowSizes.mobile; } @@ -40,7 +45,11 @@ function getWindowSize() { * with mediaquery). We don't return `undefined` on purpose, to make it more * explicit. */ -export function useWindowSize(): WindowSize { +export function useWindowSize({ + desktopBreakpoint = DesktopBreakpoint, +}: { + desktopBreakpoint?: number; +} = {}): WindowSize { const [windowSize, setWindowSize] = useState( () => // super important to return a constant value to avoid hydration mismatch @@ -50,7 +59,7 @@ export function useWindowSize(): WindowSize { useEffect(() => { function updateWindowSize() { - setWindowSize(getWindowSize()); + setWindowSize(getWindowSize(desktopBreakpoint)); } updateWindowSize(); @@ -60,7 +69,7 @@ export function useWindowSize(): WindowSize { return () => { window.removeEventListener('resize', updateWindowSize); }; - }, []); + }, [desktopBreakpoint]); return windowSize; } diff --git a/website/docs/styling-layout.mdx b/website/docs/styling-layout.mdx index 369c688ea5..b4b296dc62 100644 --- a/website/docs/styling-layout.mdx +++ b/website/docs/styling-layout.mdx @@ -180,6 +180,12 @@ Docusaurus uses `996px` as the cutoff between mobile screen width and desktop. I } ``` +:::tip Customizing the breakpoint + +Some React components, such as the header and the sidebar, implement different JavaScript logic when in mobile view. If you change the breakpoint value in your custom CSS, you probably also want to update the invocations of the `useWindowSize` hook by [swizzling](./swizzling.mdx) the components it's used in and passing an explicit option argument. + +::: + ## CSS modules {#css-modules} To style your components using [CSS Modules](https://github.com/css-modules/css-modules), name your stylesheet files with the `.module.css` suffix (e.g. `welcome.module.css`). Webpack will load such CSS files as CSS modules and you have to reference the class names as properties of the imported CSS module (as opposed to using plain strings). This is similar to the convention used in [Create React App](https://facebook.github.io/create-react-app/docs/adding-a-css-modules-stylesheet).