Skip to content

feat: highlight active item in package docs sidebar#2228

Open
iiio2 wants to merge 7 commits intonpmx-dev:mainfrom
iiio2:feat/highlight-active-item-in-doc-sidebar
Open

feat: highlight active item in package docs sidebar#2228
iiio2 wants to merge 7 commits intonpmx-dev:mainfrom
iiio2:feat/highlight-active-item-in-doc-sidebar

Conversation

@iiio2
Copy link
Copy Markdown
Contributor

@iiio2 iiio2 commented Mar 23, 2026

Clicking a sidebar TOC item on the docs page navigates to the section, but the sidebar doesn't visually indicate which item is currently selected. Now we can see which item is selected.

Before:

before-docs-one

After:

after-docs-one

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Mar 23, 2026 4:46pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Mar 23, 2026 4:46pm
npmx-lunaria Ignored Ignored Mar 23, 2026 4:46pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 23, 2026

📝 Walkthrough

Walkthrough

Client-side TOC active-link tracking was added to the package docs page. A tocContainerRef template ref and associated functions clear any existing toc-active class and apply it to the a whose href matches window.location.hash (using CSS.escape). The update runs on mount, on hashchange, when docsData.value?.toc changes (via a watcher with nextTick), and after TOC clicks (event delegation). The TOC container now attaches the ref and click handler, and new CSS styles a.toc-active.

Suggested labels

help wanted

Suggested reviewers

  • danielroe
  • alexdln
🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description clearly relates to the changeset: it explains that the sidebar TOC now visually indicates the currently selected item.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

@ghostdevv ghostdevv left a comment

Choose a reason for hiding this comment

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

Hmm I wonder if we should use an IntersectionObserver instead so that it highlights the top most visible one? That would mean that it wouldn't always show the one you have in your hash though, but when you load the page it would which I think works?

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5dadc5e7-0551-4e57-b284-b1c15d68840c

📥 Commits

Reviewing files that changed from the base of the PR and between 6181ed1 and c8a5468.

📒 Files selected for processing (1)
  • app/pages/package-docs/[...path].vue

Comment on lines +159 to +163
function onTocClick(e: Event) {
const link = (e.target as HTMLElement).closest('a[href^="#"]')
if (link) {
nextTick(updateActiveTocLink)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read-only verification: find cast-based EventTarget.closest usage patterns in Vue files.
rg -nP --type=vue -C2 '\(e\.target as HTMLElement\)\.closest\('

Repository: npmx-dev/npmx.dev

Length of output: 88


🏁 Script executed:

# First, locate and read the specific file
cat -n app/pages/package-docs/[...path].vue | head -180 | tail -40

Repository: npmx-dev/npmx.dev

Length of output: 1286


🏁 Script executed:

# Check the actual file structure and read lines around 159-163
wc -l app/pages/package-docs/[...path].vue && echo "---" && sed -n '150,170p' app/pages/package-docs/[...path].vue

Repository: npmx-dev/npmx.dev

Length of output: 587


🏁 Script executed:

# Find similar patterns in .vue files
fd -e vue -x rg -l 'e\.target' {} \; | head -5

Repository: npmx-dev/npmx.dev

Length of output: 230


🏁 Script executed:

# Search for similar EventTarget.closest patterns in .vue files
fd -e vue -x rg -n 'e\.target.*\.closest\|target.*as HTMLElement' {} +

Repository: npmx-dev/npmx.dev

Length of output: 6990


🏁 Script executed:

# Search for similar patterns in all Vue files
rg -n 'target as HTMLElement' app/

Repository: npmx-dev/npmx.dev

Length of output: 491


Guard EventTarget before calling closest().

e.target is not guaranteed to be an HTMLElement; this cast can fail at runtime on non-Element targets. Add a runtime instanceof Element check first.

🛠 Proposed fix
 function onTocClick(e: Event) {
-  const link = (e.target as HTMLElement).closest('a[href^="#"]')
+  const target = e.target
+  if (!(target instanceof Element)) return
+  const link = target.closest('a[href^="#"]')
   if (link) {
     nextTick(updateActiveTocLink)
   }
 }

Per the coding guidelines, ensure strictly type-safe code by checking types at runtime before calling methods that don't exist on the source type.

howwohmm

This comment was marked as spam.

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.

3 participants