fix: Sidebar accounts for sticky header height via ResizeObserver

Measures the review header dynamically and offsets the sidebar's sticky
top and max-height accordingly, eliminating the gap when scrolled.
This commit is contained in:
Lukas May
2026-03-06 11:15:02 +01:00
parent d4b466ce6d
commit 09624e9cb7

View File

@@ -1,4 +1,4 @@
import { useCallback, useMemo, useRef, useState } from "react";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { toast } from "sonner";
import { Loader2 } from "lucide-react";
import { trpc } from "@/lib/trpc";
@@ -18,6 +18,18 @@ export function ReviewTab({ initiativeId }: ReviewTabProps) {
const [selectedCommit, setSelectedCommit] = useState<string | null>(null);
const [viewedFiles, setViewedFiles] = useState<Set<string>>(new Set());
const fileRefs = useRef<Map<string, HTMLDivElement>>(new Map());
const headerRef = useRef<HTMLDivElement>(null);
const [headerHeight, setHeaderHeight] = useState(0);
useEffect(() => {
const el = headerRef.current;
if (!el) return;
const ro = new ResizeObserver(([entry]) => {
setHeaderHeight(entry.contentRect.height);
});
ro.observe(el);
return () => ro.disconnect();
}, []);
const toggleViewed = useCallback((filePath: string) => {
setViewedFiles(prev => {
@@ -313,6 +325,7 @@ export function ReviewTab({ initiativeId }: ReviewTabProps) {
return (
<div className="rounded-lg border border-border bg-card">
{/* Header: phase selector + toolbar */}
<div ref={headerRef}>
<ReviewHeader
phases={reviewablePhases.map((p) => ({ id: p.id, name: p.name, status: p.status }))}
activePhaseId={activePhaseId}
@@ -331,12 +344,19 @@ export function ReviewTab({ initiativeId }: ReviewTabProps) {
viewedCount={viewedFiles.size}
totalCount={allFiles.length}
/>
</div>
{/* Main content area — sidebar always rendered to preserve state */}
<div className="grid grid-cols-1 lg:grid-cols-[260px_1fr] rounded-b-lg">
{/* Left: Sidebar — sticky to viewport, scrolls independently */}
<div className="border-r border-border">
<div className="sticky top-0 h-screen max-h-[calc(100vh-4rem)] overflow-hidden">
<div
className="sticky overflow-hidden"
style={{
top: `${headerHeight}px`,
maxHeight: `calc(100vh - ${headerHeight}px)`,
}}
>
<ReviewSidebar
files={allFiles}
comments={comments}