Keep active sidebar item visible across navigation#380
Conversation
Anchors to the current page's link (aria-current) and scrolls the sidebar the minimum amount to reveal it, rather than persisting a pixel offset in sessionStorage. Pixel offsets can land on the wrong item when the sidebar's contents differ between sections; an active-item anchor stays correct by construction and needs no scroll/click listeners or stored state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
|
Firetiger deploy monitoring skipped This PR didn't match the auto-monitor filter configured on your GitHub connection:
Reason: This PR modifies frontend sidebar navigation behavior in what appears to be a documentation site (Mintlify), not the kernel API endpoints or Temporal workflows specified in the filter. To monitor this PR anyway, reply with |
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8af03351eb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return sb.querySelector( | ||
| "a[aria-current='page'], a[aria-current='true'], a[data-active='true']" | ||
| ); |
There was a problem hiding this comment.
Use Mintlify's active sidebar selector
On Mintlify pages that use the documented sidebar active state (#sidebar-content li[data-active]), this lookup returns null because it only checks attributes on the <a> and requires data-active='true'. In that case showActive() never runs past the active-link check, so the new sidebar-scroll behavior silently no-ops on the pages it was added to fix; include the li[data-active]/presence selector and resolve its contained link or element.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Stale comment
Risk assessment: Low risk.
This PR adds one client-side docs script,
sidebar-scroll.js, that observes page load and history navigation, finds the active sidebar link, and adjusts the sidebar scroll position. The change is user-facing across the docs shell, so I’m classifying it above Very Low, but its scope is isolated to DOM scroll behavior and it doesn’t modify documentation content, backend logic, auth, data handling, dependencies, build configuration, or infrastructure.I found no
CODEOWNERSfile in the repo. The current head commit already has an approval, so I’m leaving this assessment as a comment rather than approving again.Sent by Cursor Automation: Assign PR reviewers
Mintlify has no navigation event, but it rewrites the data-current-path attribute on <html> on every client-side route change. Observing that attribute replaces the history.pushState/replaceState monkeypatch and the setInterval poll, and removes the stale active-link race since the attribute flips in the same commit as the sidebar's aria-current. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Risk assessment: Low risk.
This PR adds a single client-side docs script, sidebar-scroll.js, that keeps the active sidebar link visible by observing Mintlify’s data-current-path changes and adjusting sidebar scroll position. The latest update narrows the implementation from history monkey-patching and polling to a scoped MutationObserver, so the risk has not increased since the earlier approval.
The change is user-facing across the docs shell, so I’m classifying it above Very Low, but it’s isolated to DOM scroll behavior and does not modify docs content, backend logic, auth, data handling, dependencies, build configuration, or infrastructure.
I found no CODEOWNERS file. The PR is already approved, so I’m leaving this as a risk-assessment comment rather than adding another approval.
Sent by Cursor Automation: Assign PR reviewers
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit e2ef311. Configure here.
| "a[aria-current='page'], a[aria-current='true'], a[data-active='true']" | ||
| ); | ||
| // Guard against acting on the previous page's link before the DOM updates. | ||
| if (!link || link.pathname !== location.pathname) return; |
There was a problem hiding this comment.
No retry after race condition guard causes silent failure
Medium Severity
On SPA navigation, data-current-path on <html> triggers the MutationObserver, which schedules a single requestAnimationFrame(showActive). If Mintlify's React render cycle hasn't yet updated aria-current on sidebar links by the time that frame fires, the guard on line 24 (link.pathname !== location.pathname) correctly bails out to avoid acting on the old link — but there is no retry. The feature silently becomes a no-op for that navigation. The PR description mentions "polling until the sidebar mounts plus one 150ms re-apply" but neither mechanism is actually implemented.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit e2ef311. Configure here.




Summary
Alternative to #379. Instead of saving the sidebar's pixel
scrollToptosessionStorageand restoring it, this scrolls the sidebar the minimum amount needed to bring the current page's link into view after navigation.sidebar-scroll.jsat the repo root (Mintlify auto-injects content-dir.json every page).aria-current="page"+ fallbacks) and nudges the sidebar so it's visible, with a 24px margin. No-op if it's already on screen.pushState/replaceState/popstate) and full loads, polling until the sidebar mounts plus one 150ms re-apply to survive a late re-render.Why this over #379
A saved pixel offset assumes the sidebar's contents are identical across pages. Mintlify expands/collapses groups per section, so the same
scrollTopcan map to a different item on a different page — landing you in the wrong place. Anchoring to the active item is correct by construction and drops all the persistence machinery (nosessionStorage, no scroll/click listeners, no debounce).Net effect is the same for the common case (clicking an item just below where you are): with
block: nearest-style math, nothing moves because the target is already visible.Test plan (staging)
Notes
aria-current="page". If staging shows it doesn't, adjust the selector infindActiveLink.mintlify devrequires an LTS Node and this machine is on Node 25.🤖 Generated with Claude Code
Note
Low Risk
Docs-only client-side UI behavior with no auth, API, or data changes; risk is limited to Mintlify DOM/attribute assumptions.
Overview
Adds
sidebar-scroll.jsat the repo root so Mintlify auto-loads a small client script on every docs page.After load and on SPA navigations (via a
MutationObserveron<html>’sdata-current-path), it finds the scrollable sidebar, locates the active nav link (aria-current/data-active), and adjustsscrollToponly enough to keep that link visible with a 24px margin. It skips work when the link already fits or when the active link’spathnamedoes not match the current URL (avoids stale DOM).This replaces pixel
scrollToppersistence with anchor-to-active-item scrolling so sidebar structure changes across pages do not land on the wrong item.Reviewed by Cursor Bugbot for commit e2ef311. Bugbot is set up for automated code reviews on this repo. Configure here.