fix(theme): misaligned outline indicator\

fixes #3449
pull/3458/head
Divyansh Singh 6 months ago
parent cd8ee6fb32
commit 910b2125bb

@ -1,9 +1,9 @@
import { reactive, inject, markRaw, nextTick, readonly } from 'vue'
import type { Component, InjectionKey } from 'vue' import type { Component, InjectionKey } from 'vue'
import { inject, markRaw, nextTick, reactive, readonly } from 'vue'
import type { Awaitable, PageData, PageDataPayload } from '../shared'
import { notFoundPageData, treatAsHtml } from '../shared' import { notFoundPageData, treatAsHtml } from '../shared'
import type { PageData, PageDataPayload, Awaitable } from '../shared'
import { inBrowser, withBase } from './utils'
import { siteDataRef } from './data' import { siteDataRef } from './data'
import { getScrollOffset, inBrowser, withBase } from './utils'
export interface Route { export interface Route {
path: string path: string
@ -261,26 +261,6 @@ export function scrollTo(el: Element, hash: string, smooth = false) {
} }
if (target) { if (target) {
let scrollOffset = siteDataRef.value.scrollOffset
let offset = 0
let padding = 24
if (typeof scrollOffset === 'object' && 'padding' in scrollOffset) {
padding = scrollOffset.padding
scrollOffset = scrollOffset.selector
}
if (typeof scrollOffset === 'number') {
offset = scrollOffset
} else if (typeof scrollOffset === 'string') {
offset = tryOffsetSelector(scrollOffset, padding)
} else if (Array.isArray(scrollOffset)) {
for (const selector of scrollOffset) {
const res = tryOffsetSelector(selector, padding)
if (res) {
offset = res
break
}
}
}
const targetPadding = parseInt( const targetPadding = parseInt(
window.getComputedStyle(target).paddingTop, window.getComputedStyle(target).paddingTop,
10 10
@ -288,7 +268,7 @@ export function scrollTo(el: Element, hash: string, smooth = false) {
const targetTop = const targetTop =
window.scrollY + window.scrollY +
target.getBoundingClientRect().top - target.getBoundingClientRect().top -
offset + getScrollOffset() +
targetPadding targetPadding
function scrollToTarget() { function scrollToTarget() {
// only smooth scroll if distance is smaller than screen height. // only smooth scroll if distance is smaller than screen height.
@ -300,14 +280,6 @@ export function scrollTo(el: Element, hash: string, smooth = false) {
} }
} }
function tryOffsetSelector(selector: string, padding: number): number {
const el = document.querySelector(selector)
if (!el) return 0
const bot = el.getBoundingClientRect().bottom
if (bot < 0) return 0
return bot + padding
}
function handleHMR(route: Route): void { function handleHMR(route: Route): void {
// update route.data on HMR updates of active page // update route.data on HMR updates of active page
if (import.meta.hot) { if (import.meta.hot) {

@ -107,3 +107,36 @@ export function defineClientComponent(
} }
} }
} }
export function getScrollOffset() {
let scrollOffset = siteDataRef.value.scrollOffset
let offset = 0
let padding = 24
if (typeof scrollOffset === 'object' && 'padding' in scrollOffset) {
padding = scrollOffset.padding
scrollOffset = scrollOffset.selector
}
if (typeof scrollOffset === 'number') {
offset = scrollOffset
} else if (typeof scrollOffset === 'string') {
offset = tryOffsetSelector(scrollOffset, padding)
} else if (Array.isArray(scrollOffset)) {
for (const selector of scrollOffset) {
const res = tryOffsetSelector(selector, padding)
if (res) {
offset = res
break
}
}
}
return offset
}
function tryOffsetSelector(selector: string, padding: number): number {
const el = document.querySelector(selector)
if (!el) return 0
const bot = el.getBoundingClientRect().bottom
if (bot < 0) return 0
return bot + padding
}

@ -1,8 +1,9 @@
import type { DefaultTheme } from 'vitepress/theme' import type { DefaultTheme } from 'vitepress/theme'
import { onMounted, onUnmounted, onUpdated, type Ref } from 'vue' import { onMounted, onUnmounted, onUpdated, type Ref } from 'vue'
import { getScrollOffset } from '../../app/utils'
import type { Header } from '../../shared' import type { Header } from '../../shared'
import { useAside } from './aside'
import { throttleAndDebounce } from '../support/utils' import { throttleAndDebounce } from '../support/utils'
import { useAside } from './aside'
// cached list of anchor elements from resolveHeaders // cached list of anchor elements from resolveHeaders
const resolvedHeaders: { element: HTMLHeadElement; link: string }[] = [] const resolvedHeaders: { element: HTMLHeadElement; link: string }[] = []
@ -179,7 +180,7 @@ export function useActiveAnchor(
// find the last header above the top of viewport // find the last header above the top of viewport
let activeLink: string | null = null let activeLink: string | null = null
for (const { link, top } of headers) { for (const { link, top } of headers) {
if (top > scrollY + offsetDocTop) { if (top > scrollY + offsetDocTop + getScrollOffset()) {
break break
} }
activeLink = link activeLink = link

Loading…
Cancel
Save