feat(theme): sidebar auto scroll into active link (#604)

This commit is contained in:
pengzhanbo 2025-05-21 22:55:26 +08:00 committed by GitHub
parent 7592eafd38
commit c9ead12e35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 11 deletions

View File

@ -2,7 +2,7 @@
import VPSidebarGroup from '@theme/VPSidebarGroup.vue'
import VPTransitionFadeSlideY from '@theme/VPTransitionFadeSlideY.vue'
import { useScrollLock } from '@vueuse/core'
import { onMounted, ref, watch } from 'vue'
import { nextTick, onMounted, ref, watch } from 'vue'
import { useRoutePath } from 'vuepress/client'
import { useData, useSidebar } from '../composables/index.js'
import { inBrowser } from '../utils/index.js'
@ -31,19 +31,31 @@ watch(
{ immediate: true, flush: 'post' },
)
/**
* Scroll to active item
*/
onMounted(() => {
const activeItem = document.querySelector(
`.vp-sidebar .vp-link[href*="${routePath.value}"]`,
)
if (!activeItem || !navEl.value)
return
watch(sidebarKey, async () => {
await nextTick()
const activeItem = document.querySelector(
`.vp-sidebar .vp-link[href*="${routePath.value}"]`,
)
if (!navEl.value)
return
const { top: navTop, height: navHeight } = navEl.value.getBoundingClientRect()
const { top: activeTop, height: activeHeight }
if (!activeItem) {
//
setTimeout(() => navEl.value?.scrollTo(0, 0), 200)
return
}
const { top: navTop, height: navHeight } = navEl.value.getBoundingClientRect()
const { top: activeTop, height: activeHeight }
= activeItem.getBoundingClientRect()
if (activeTop < navTop || activeTop + activeHeight > navTop + navHeight)
activeItem.scrollIntoView({ block: 'center' })
if (activeTop < navTop || activeTop + activeHeight > navTop + navHeight)
activeItem.scrollIntoView({ block: 'center' })
}, { immediate: true, flush: 'post' })
})
</script>

View File

@ -24,13 +24,18 @@ export function resolveNavLink(link: string): ResolvedNavItemWithLink {
return notFound
? { text: path, link: path }
: {
text: meta.title || path,
text: meta.title || normalizeTitleWithPath(path),
link: path,
icon: meta.icon,
badge: meta.badge,
}
}
function normalizeTitleWithPath(path: string): string {
path = path.replace(/index\.html?$/i, '').replace(/\.html?$/i, '').replace(/\/$/, '')
return decodeURIComponent(path.slice(path.lastIndexOf('/') + 1))
}
export function normalizeLink(base = '', link = ''): string {
return isLinkAbsolute(link) || isLinkWithProtocol(link)
? link