diff --git a/CHANGELOG.md b/CHANGELOG.md index f0a70869f..2c110b24b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 so no canonical names a redirect. `og:url` is built by the same function, so the two cannot disagree. Nothing is emitted without `site_url` ([#207](https://github.com/QuantEcon/quantecon-theme.mystmd/issues/207)) ([#227](https://github.com/QuantEcon/quantecon-theme.mystmd/pull/227)). +- The "On this page" outline lists h4 subsections, which the Sphinx panel lists + and this one left out: a reader inside an h4 saw its h3 marked with nothing + below it. The panel is now a tree of any depth, and the Sphinx expansion rule + applies at every level of it — the current entry's own sub-list and those of + all its ancestors are open, while only the current entry itself is marked. + h4 entries are indented one step further than h3s. h5 and deeper are still + not listed + ([#208](https://github.com/QuantEcon/quantecon-theme.mystmd/issues/208)) ([#228](https://github.com/QuantEcon/quantecon-theme.mystmd/pull/228)). ### Changed - **Breaking: the Launch control is now opt-in and explicitly configured.** It diff --git a/app/components/Outline.tsx b/app/components/Outline.tsx index 0f3cce9fd..adcdb4070 100644 --- a/app/components/Outline.tsx +++ b/app/components/Outline.tsx @@ -52,10 +52,12 @@ export function BackToTop() { * `sticky`: the wrapper is `self-start`, so a sticky child would have zero * travel, and the grid declares no rows for it to span. `left`/`right` stay * `auto`, so the panel keeps its static position in the margin track. - * - h3 entries nest under their h2 and collapse to the active branch: at the - * top of the page only the sections show; scrolling into a section expands - * its subsections, the current one (section or subsection) is marked, and - * the parent of a current subsection is expanded but not marked. Past + * - h2 to h4 nest into a tree of any depth, which collapses to the active + * branch: at the top of the page only the sections show, and a branch opens + * when the current entry is inside it. The rule runs at every level -- the + * current entry's own sub-list and those of all its ancestors are open -- + * so a current h3 shows its h4s. Only the current entry is marked, at + * whatever depth it sits; its ancestors are open but unmarked. Past * `max-height` the panel scrolls internally. * - Enumerators come from the heading itself (`span.select-none`, "3.1"), * plus the period the h1 uses -- never a number computed from the list @@ -71,14 +73,15 @@ export function Outline({ }) { const Link = useLinkProvider(); const baseurl = useBaseurl(); - const { headings } = useHeaders('main h2, main h3', 3); + // h2 to h4, the depths the Sphinx panel lists. `maxdepth` stays 3 because + // upstream renumbers levels from the shallowest heading on the page and keeps + // `level < maxdepth + 1`: with an h2 present, an h4 is level 3. + const { headings } = useHeaders('main h2, main h3, main h4', 3); const currentId = useActiveHeading(headings); const tree = nest(headings); - // The current item's own sub-list, and every ancestor of the current item, - // are expanded; nothing else is. - const expandedId = tree.find( - (branch) => branch.id === currentId || branch.children.some((c) => c.id === currentId) - )?.id; + // The current entry's own sub-list and those of all its ancestors are open; + // nothing else is. + const open = openBranches(tree, currentId); return (