Fix search scrolling (#1982)

This commit is contained in:
Zane
2025-04-01 11:50:55 -07:00
committed by GitHub
parent 177cdbe0f2
commit efabdbd397
@@ -102,26 +102,39 @@ export const SearchView: React.FC<PropsWithChildren<SearchViewProps>> = ({
const marks = containerRef.current.querySelectorAll('mark'); const marks = containerRef.current.querySelectorAll('mark');
const mark = marks[index] as HTMLElement; const mark = marks[index] as HTMLElement;
if (!mark) return;
if (mark) { // Update highlight
// Update highlight marks.forEach((m) => m.classList.remove('current'));
marks.forEach((m) => m.classList.remove('current')); mark.classList.add('current');
mark.classList.add('current');
// Calculate position to center the mark in the viewport // Find the viewport element
const markRect = mark.getBoundingClientRect(); const viewport = mark.closest('[data-radix-scroll-area-viewport]') as HTMLElement;
const viewportRect = mark if (!viewport) return;
.closest('[data-radix-scroll-area-viewport]')
?.getBoundingClientRect();
if (viewportRect) { // Get measurements
const targetPosition = mark.offsetTop - viewportRect.height / 2 + markRect.height / 2; const viewportRect = viewport.getBoundingClientRect();
scrollAreaRef.current.scrollToPosition({ const markRect = mark.getBoundingClientRect();
top: targetPosition, const currentScrollTop = viewport.scrollTop;
behavior: 'smooth',
}); // Calculate how far the element is from the top of the viewport
} const elementRelativeToViewport = markRect.top - viewportRect.top;
}
// Calculate the new scroll position that would center the element
const targetPosition =
currentScrollTop + elementRelativeToViewport - (viewportRect.height - markRect.height) / 2;
// Ensure we don't scroll past the bottom
const maxScroll = viewport.scrollHeight - viewport.clientHeight;
const finalPosition = Math.max(0, Math.min(targetPosition, maxScroll));
// Use requestAnimationFrame to ensure DOM measurements are accurate
requestAnimationFrame(() => {
scrollAreaRef.current?.scrollToPosition({
top: finalPosition,
behavior: 'smooth',
});
});
}; };
const clearHighlights = () => { const clearHighlights = () => {