packages/docusaurus-theme/src/theme/DocRoot/Layout/index.tsx (51 lines of code) (raw):

import { useEffect, useState, JSX } from 'react'; import { css } from '@emotion/react'; import { useDocsSidebar } from '@docusaurus/plugin-content-docs/client'; import useIsBrowser from '@docusaurus/useIsBrowser'; import BackToTopButton from '@theme-original/BackToTopButton'; import type { Props } from '@theme-original/DocRoot/Layout'; import DocRootLayoutSidebar from '@theme-original/DocRoot/Layout/Sidebar'; import DocRootLayoutMain from './Main'; // converted from css modules to Emotion const styles = { docRoot: css` display: flex; width: 100%; `, docsWrapper: css` display: flex; flex: 1 0 auto; `, }; export default function DocRootLayout({ children }: Props): JSX.Element { const isBrowser = useIsBrowser(); const sidebar = useDocsSidebar(); const [hiddenSidebarContainer, setHiddenSidebarContainer] = useState(false); // Replicate browser hash scroll behavior to trigger it after the MDX content // is rendered. Timeout = 0 should do the job here just fine as the effect // will get executed at next render cycle when all elements are (hopefully) // already in the DOM. useEffect(() => { if (!isBrowser) { return; } if (window.location.hash) { setTimeout(() => { const element = document.getElementById( window.location.hash.substring(1), ); element?.scrollIntoView(true); }, 100); } }, [isBrowser]); return ( <div css={styles.docsWrapper}> <BackToTopButton /> <div css={styles.docRoot}> {sidebar && ( <DocRootLayoutSidebar sidebar={sidebar.items} hiddenSidebarContainer={hiddenSidebarContainer} setHiddenSidebarContainer={setHiddenSidebarContainer} /> )} <DocRootLayoutMain hiddenSidebarContainer={hiddenSidebarContainer}> {children} </DocRootLayoutMain> </div> </div> ); }