diff --git a/src/Documentation/ui/DocumentationRoot.tsx b/src/Documentation/ui/DocumentationRoot.tsx index d2266207b..a5ee1b08c 100644 --- a/src/Documentation/ui/DocumentationRoot.tsx +++ b/src/Documentation/ui/DocumentationRoot.tsx @@ -1,12 +1,15 @@ -import React, { useState } from "react"; +import React, { useLayoutEffect, useState } from "react"; import Button from "@mui/material/Button"; import { MD } from "../../ui/MD/MD"; -import { getPage } from "../root"; -import { Navigator, useHistory } from "../../ui/React/Documentation"; +import { Navigator, windowTopPositionOfPages, useHistory } from "../../ui/React/Documentation"; import { CONSTANTS } from "../../Constants"; import { asFilePath, resolveFilePath } from "../../Paths/FilePath"; +import Box from "@mui/material/Box"; +import { Settings } from "../../Settings/Settings"; +import { Router } from "../../ui/GameRoot"; +import { Page } from "../../ui/Router"; export function DocumentationRoot({ docPage }: { docPage?: string }): React.ReactElement { const history = useHistory(); @@ -15,7 +18,6 @@ export function DocumentationRoot({ docPage }: { docPage?: string }): React.Reac history.push(asFilePath(deepLink)); setDeepLink(undefined); } - const page = getPage(history.page); const navigator = { navigate(relPath: string, external: boolean) { const newPath = resolveFilePath("./" + relPath, history.page); @@ -30,19 +32,30 @@ export function DocumentationRoot({ docPage }: { docPage?: string }): React.Reac return; } history.push(newPath); - - // Reset scroll to the top of the page. - window.scrollTo(0, 0); }, }; + // We need to use "useLayoutEffect" instead of "useEffect". "useLayoutEffect" is fired before the browser repaints the + // screen. + useLayoutEffect(() => { + return () => { + if (Router.page() !== Page.Documentation) { + windowTopPositionOfPages.set(history.page, window.scrollY); + } + }; + }, [history]); + return ( <> - - - - - + + + + + + + + + ); } diff --git a/src/ui/MD/MD.tsx b/src/ui/MD/MD.tsx index 42ff77ad9..6e755c577 100644 --- a/src/ui/MD/MD.tsx +++ b/src/ui/MD/MD.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; import ReactMarkdown from "react-markdown"; import { TableHead } from "@mui/material"; import remarkGfm from "remark-gfm"; @@ -7,8 +7,20 @@ import { code, Pre } from "./code"; import { A } from "./a"; import remarkMath from "remark-math"; import rehypeMathjax from "rehype-mathjax/svg"; +import { FilePath } from "../../Paths/FilePath"; +import { getPage } from "../../Documentation/root"; + +export function MD(props: { pageFilePath: FilePath; top: number }): React.ReactElement { + const pageContent = getPage(props.pageFilePath); + + useEffect(() => { + // This is a workaround. window.scrollTo does not work when we switch from Documentation tab to another tab, then + // switch back. + setTimeout(() => { + window.scrollTo({ top: props.top, behavior: "instant" }); + }, 0); + }); -export function MD(props: { md: string }): React.ReactElement { return ( - {props.md} + {String(pageContent)} ); } diff --git a/src/ui/React/Documentation.tsx b/src/ui/React/Documentation.tsx index d3826afd3..36b99b4f9 100644 --- a/src/ui/React/Documentation.tsx +++ b/src/ui/React/Documentation.tsx @@ -9,6 +9,8 @@ export const Navigator = React.createContext({ navigate: () => undefi export const useNavigator = (): Navigator => useContext(Navigator); +export const windowTopPositionOfPages = new Map(); + interface History { pages: FilePath[]; page: FilePath; @@ -59,13 +61,22 @@ export const HistoryProvider = (props: React.PropsWithChildren): React.R page: defaultPage, pages: [], push(p: FilePath) { - setHistory((h) => onPush(h, p)); + setHistory((h) => { + windowTopPositionOfPages.set(h.page, window.scrollY); + return onPush(h, p); + }); }, pop() { - setHistory((h) => onPop(h)); + setHistory((h) => { + windowTopPositionOfPages.set(h.page, window.scrollY); + return onPop(h); + }); }, home() { - setHistory((h) => onHome(h)); + setHistory((h) => { + windowTopPositionOfPages.set(h.page, window.scrollY); + return onHome(h); + }); }, }); return {props.children};