Skip to content

Keep active sidebar item visible across navigation#380

Closed
ehfeng wants to merge 3 commits into
mainfrom
hypeship/sidebar-show-active-item
Closed

Keep active sidebar item visible across navigation#380
ehfeng wants to merge 3 commits into
mainfrom
hypeship/sidebar-show-active-item

Conversation

@ehfeng
Copy link
Copy Markdown
Contributor

@ehfeng ehfeng commented May 27, 2026

Summary

Alternative to #379. Instead of saving the sidebar's pixel scrollTop to sessionStorage and restoring it, this scrolls the sidebar the minimum amount needed to bring the current page's link into view after navigation.

  • Adds sidebar-scroll.js at the repo root (Mintlify auto-injects content-dir .js on every page).
  • Finds the active link (aria-current="page" + fallbacks) and nudges the sidebar so it's visible, with a 24px margin. No-op if it's already on screen.
  • Re-applies on SPA route changes (patched 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 scrollTop can 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 (no sessionStorage, 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)

  • Navigate to a page whose sidebar item sits far down a long section; confirm the active item is visible in the sidebar after the page loads.
  • Click a deep link, then the one just below it — sidebar should not jump.
  • Hard-refresh on a deep page — active item visible.
  • Confirm only the sidebar scrolls (main content scroll position untouched) and no console errors.

Notes

  • Depends on Mintlify marking the active link with aria-current="page". If staging shows it doesn't, adjust the selector in findActiveLink.
  • Couldn't test locally — mintlify dev requires 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.js at the repo root so Mintlify auto-loads a small client script on every docs page.

After load and on SPA navigations (via a MutationObserver on <html>’s data-current-path), it finds the scrollable sidebar, locates the active nav link (aria-current / data-active), and adjusts scrollTop only enough to keep that link visible with a 24px margin. It skips work when the link already fits or when the active link’s pathname does not match the current URL (avoids stale DOM).

This replaces pixel scrollTop persistence 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.

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>
@mintlify
Copy link
Copy Markdown
Contributor

mintlify Bot commented May 27, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Kernel 🟢 Ready View Preview May 27, 2026, 5:55 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@firetiger-agent
Copy link
Copy Markdown

Firetiger deploy monitoring skipped

This PR didn't match the auto-monitor filter configured on your GitHub connection:

Any PR that changes the kernel API. Monitor changes to API endpoints (packages/api/cmd/api/) and Temporal workflows (packages/api/lib/temporal) in the kernel repo

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 @firetiger monitor this.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cursor[bot]
cursor Bot approved these changes May 27, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread sidebar-scroll.js Outdated
Comment on lines +18 to +20
return sb.querySelector(
"a[aria-current='page'], a[aria-current='true'], a[data-active='true']"
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 CODEOWNERS file in the repo. The current head commit already has an approval, so I’m leaving this assessment as a comment rather than approving again.

Open in Web View Automation 

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>
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Open in Web View Automation 

Sent by Cursor Automation: Assign PR reviewers

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

Comment thread sidebar-scroll.js
"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;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e2ef311. Configure here.

@ehfeng ehfeng closed this May 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant