Docs: Fixed broken navigation menu on mobile
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 20s
CI / quality (pull_request) Successful in 20s
CI / build (pull_request) Successful in 23s
CI / security (pull_request) Successful in 43s
CI / typecheck (pull_request) Successful in 53s
CI / integration_tests (pull_request) Successful in 4m16s
CI / unit_tests (pull_request) Successful in 5m51s
CI / docker (pull_request) Successful in 8s
CI / benchmark-regression (pull_request) Successful in 17m24s
CI / coverage (pull_request) Successful in 21m32s
CI / lint (push) Successful in 14s
CI / build (push) Successful in 14s
CI / quality (push) Successful in 16s
CI / security (push) Successful in 27s
CI / typecheck (push) Successful in 42s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 2m40s
CI / benchmark-publish (push) Successful in 8m35s
CI / unit_tests (push) Successful in 9m44s
CI / docker (push) Successful in 51s
CI / coverage (push) Successful in 22m30s

This commit was merged in pull request #140.
This commit is contained in:
2026-02-22 01:12:16 -05:00
parent 431f827ac4
commit e40dd75478
2 changed files with 94 additions and 11 deletions
+22
View File
@@ -550,9 +550,31 @@
});
}
// ── Desktop detection ────────────────────────────────────────────────
//
// This entire script is designed for the desktop persistent sidebar
// (≥76.25em). On mobile, Material uses a slide-out drawer with its
// own drill-down navigation, scroll management, and back-button
// behaviour. Running our DOM restructuring (convertPageItems,
// initCollapsibleToc, lockActiveAncestorSections) on mobile breaks
// the drawer's scroll container and makes it impossible to scroll
// past the visible items.
//
// We use matchMedia to detect the breakpoint and only bootstrap on
// desktop. On resize/orientation changes that cross the breakpoint,
// the page reloads via Material's SPA system anyway, so we don't need
// a live resize listener.
var desktopQuery = window.matchMedia("(min-width: 76.25em)");
function isDesktop() {
return desktopQuery.matches;
}
// ── Bootstrap ───────────────────────────────────────────────────────
function bootstrap() {
if (!isDesktop()) return; // skip all DOM manipulation on mobile
initCollapsibleToc();
convertPageItems();
lockActiveAncestorSections();
+72 -11
View File
@@ -105,11 +105,19 @@
* when unchecked. Without this, the <nav> container retains residual
* height from padding/grid-rows even when the checkbox is unchecked,
* causing visible whitespace below collapsed section headings.
*
* DESKTOP ONLY (76.25em): On mobile, Material uses a slide-out drawer
* with drill-down navigation that depends on nested <nav> elements being
* in the render tree. Applying display:none on mobile breaks both the
* drill-down animation and scroll-height computation, preventing users
* from scrolling to see all nav items.
* ----------------------------------------------------------------------- */
/* Fully hide children of unchecked primary nav sections */
.md-sidebar--primary .md-nav__item--nested > .md-nav__toggle:not(:checked) ~ .md-nav {
display: none;
/* Fully hide children of unchecked primary nav sections — desktop only */
@media screen and (min-width: 76.25em) {
.md-sidebar--primary .md-nav__item--nested > .md-nav__toggle:not(:checked) ~ .md-nav {
display: none;
}
}
/* --- Leaf-page nav items: section-like behaviour ----------------------------
@@ -219,16 +227,69 @@
transform: rotate(0deg);
}
/* Hide nested nav list when collapsed (TOC items only) */
.md-nav--secondary .md-nav__item--nested.toc-collapsed > .md-nav,
.md-nav--page-toc .md-nav__item--nested.toc-collapsed > .md-nav {
display: none;
/* Hide/show nested nav list when collapsed (TOC items only).
* Desktop only on mobile the TOC is rendered within Material's drawer
* and must remain in the render tree for correct scroll behaviour. */
@media screen and (min-width: 76.25em) {
.md-nav--secondary .md-nav__item--nested.toc-collapsed > .md-nav,
.md-nav--page-toc .md-nav__item--nested.toc-collapsed > .md-nav {
display: none;
}
.md-nav--secondary .md-nav__item--nested > .md-nav,
.md-nav--page-toc .md-nav__item--nested > .md-nav {
display: block;
}
}
/* Show nested nav when expanded (TOC items only) */
.md-nav--secondary .md-nav__item--nested > .md-nav,
.md-nav--page-toc .md-nav__item--nested > .md-nav {
display: block;
/* --- Mobile sidebar scroll fix -----------------------------------------------
*
* On mobile (< 76.25em), Material renders the primary sidebar as a
* slide-out drawer. The custom toc-collapse.js script (which is
* desktop-only) restructures nav items and collapses sections, but on
* mobile we rely on Material's native drawer navigation. Ensure the
* drawer's content is scrollable when there are more items than fit on
* screen this was broken because the desktop-only display:none rules
* were interfering with the scroll container height computation, and
* the nav containers lacked explicit overflow declarations.
* ----------------------------------------------------------------------- */
@media screen and (max-width: 76.1875em) {
/* Ensure the sidebar drawer inner wrapper scrolls vertically */
.md-sidebar--primary .md-sidebar__inner {
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
/* Ensure each nav level within the mobile drawer can scroll when it
* exceeds the viewport height. Material uses absolute positioning
* and transforms for the drill-down layers; this ensures each layer
* is independently scrollable. */
.md-sidebar--primary .md-nav__list {
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
/* Prevent the overall nav from clipping its children
* Material's mobile drawer needs visible overflow on the
* horizontal axis for the slide animation, and auto on the
* vertical axis for scrolling. */
.md-sidebar--primary .md-nav--primary {
overflow: visible;
}
/* Undo any items hidden by the JS-driven toc-collapsed class that
* may have been applied before the mobile guard kicks in (race
* condition on resize or orientation change). */
.md-sidebar--primary .toc-collapsed > .md-nav {
display: block !important;
}
/* Undo the section-page forced display set by JS on active pages
* let Material's native mobile styling handle it. */
.md-nav__item--section-page > .md-nav--secondary {
display: revert !important;
}
}
/* --- Diagram lightbox (fullscreen on click) --------------------------------