fix(grid): refresh scroll target after overlay unlock (#581)

This commit is contained in:
InfinityPacer
2026-07-23 23:18:25 +08:00
committed by GitHub
parent 77c4a0f84c
commit eb5366f129
2 changed files with 48 additions and 0 deletions
@@ -70,6 +70,7 @@ let mounted = false
let pendingRevealIndex: number | null = null
let lastMeasuredColumnCount = 0
let lastMeasuredColumnWidth = 0
let documentOverlayLocked = false
const safeGap = computed(() => Math.max(0, props.gap))
const safeMinItemWidth = computed(() => Math.max(1, props.minItemWidth))
@@ -338,11 +339,20 @@ function releaseVisibleRange() {
}
function handleOverlayLockChange() {
const nextOverlayLocked = isDocumentOverlayLocked()
if (nextOverlayLocked === documentOverlayLocked) {
return
}
documentOverlayLocked = nextOverlayLocked
if (shouldPauseVirtualSync()) {
freezeVisibleRange()
return
}
invalidateScrollTargetCache()
releaseVisibleRange()
queueLayoutSync()
}
@@ -790,6 +800,7 @@ function invalidateMeasurementsForLayoutChange() {
onMounted(() => {
mounted = true
documentOverlayLocked = isDocumentOverlayLocked()
syncOverlayGridState()
scrollTarget = findScrollTarget()
addScrollListener(scrollTarget)
@@ -0,0 +1,37 @@
import ProgressiveCardGrid from '@/components/misc/ProgressiveCardGrid.vue'
import { render, waitFor } from '@testing-library/vue'
import { afterEach, describe, expect, it, vi } from 'vitest'
describe('ProgressiveCardGrid scroll target lifecycle', () => {
afterEach(() => {
document.documentElement.classList.remove('v-overlay-scroll-blocked')
})
it('recomputes the scroll target after an overlay unlocks', async () => {
const scrollParent = document.createElement('div')
const addScrollListener = vi.spyOn(scrollParent, 'addEventListener')
scrollParent.style.overflowY = 'hidden'
document.body.append(scrollParent)
document.documentElement.classList.add('v-overlay-scroll-blocked')
render(ProgressiveCardGrid, {
container: scrollParent,
props: {
items: [{ id: 1 }],
getItemKey: (item: { id: number }) => item.id,
},
slots: {
default: '<div>item</div>',
},
})
expect(addScrollListener).not.toHaveBeenCalledWith('scroll', expect.any(Function), expect.anything())
scrollParent.style.overflowY = 'auto'
document.documentElement.classList.remove('v-overlay-scroll-blocked')
await waitFor(() => {
expect(addScrollListener).toHaveBeenCalledWith('scroll', expect.any(Function), { passive: true })
})
})
})