fix: Scroll to exact comment location when clicking sidebar discussions

Adds data-comment-id attributes to comment thread rows so clicking a
discussion in the sidebar scrolls directly to the comment, not just the
file card. Includes a brief ring highlight on the target row.
This commit is contained in:
Lukas May
2026-03-06 11:09:07 +01:00
parent b1233dd013
commit 3fcfa61914
3 changed files with 18 additions and 2 deletions

View File

@@ -134,7 +134,7 @@ export function LineWithComments({
{/* Existing comments on this line */} {/* Existing comments on this line */}
{lineComments.length > 0 && ( {lineComments.length > 0 && (
<tr> <tr data-comment-id={lineComments.find((c) => !c.parentCommentId)?.id}>
<td <td
colSpan={3} colSpan={3}
className="px-3 py-2 bg-muted/20 border-y border-border/50" className="px-3 py-2 bg-muted/20 border-y border-border/50"

View File

@@ -18,6 +18,7 @@ interface ReviewSidebarProps {
files: FileDiff[]; files: FileDiff[];
comments: ReviewComment[]; comments: ReviewComment[];
onFileClick: (filePath: string) => void; onFileClick: (filePath: string) => void;
onCommentClick?: (commentId: string) => void;
selectedCommit: string | null; selectedCommit: string | null;
activeFiles: FileDiff[]; activeFiles: FileDiff[];
commits: CommitInfo[]; commits: CommitInfo[];
@@ -29,6 +30,7 @@ export function ReviewSidebar({
files, files,
comments, comments,
onFileClick, onFileClick,
onCommentClick,
selectedCommit, selectedCommit,
activeFiles, activeFiles,
commits, commits,
@@ -63,6 +65,7 @@ export function ReviewSidebar({
files={files} files={files}
comments={comments} comments={comments}
onFileClick={onFileClick} onFileClick={onFileClick}
onCommentClick={onCommentClick}
selectedCommit={selectedCommit} selectedCommit={selectedCommit}
activeFiles={activeFiles} activeFiles={activeFiles}
viewedFiles={viewedFiles} viewedFiles={viewedFiles}
@@ -172,6 +175,7 @@ function FilesView({
files, files,
comments, comments,
onFileClick, onFileClick,
onCommentClick,
selectedCommit, selectedCommit,
activeFiles, activeFiles,
viewedFiles, viewedFiles,
@@ -179,6 +183,7 @@ function FilesView({
files: FileDiff[]; files: FileDiff[];
comments: ReviewComment[]; comments: ReviewComment[];
onFileClick: (filePath: string) => void; onFileClick: (filePath: string) => void;
onCommentClick?: (commentId: string) => void;
selectedCommit: string | null; selectedCommit: string | null;
activeFiles: FileDiff[]; activeFiles: FileDiff[];
viewedFiles: Set<string>; viewedFiles: Set<string>;
@@ -248,7 +253,7 @@ function FilesView({
transition-colors hover:bg-accent/50 transition-colors hover:bg-accent/50
${thread.resolved ? "opacity-50" : ""} ${thread.resolved ? "opacity-50" : ""}
`} `}
onClick={() => onFileClick(thread.filePath)} onClick={() => onCommentClick ? onCommentClick(thread.id) : onFileClick(thread.filePath)}
> >
<div className="flex items-center gap-1.5 w-full min-w-0"> <div className="flex items-center gap-1.5 w-full min-w-0">
{thread.resolved ? ( {thread.resolved ? (

View File

@@ -259,6 +259,16 @@ export function ReviewTab({ initiativeId }: ReviewTabProps) {
} }
}, []); }, []);
const handleCommentClick = useCallback((commentId: string) => {
const el = document.querySelector(`[data-comment-id="${commentId}"]`);
if (el) {
el.scrollIntoView({ behavior: "smooth", block: "center" });
// Brief highlight flash
el.classList.add("ring-2", "ring-primary/50");
setTimeout(() => el.classList.remove("ring-2", "ring-primary/50"), 1500);
}
}, []);
const handlePhaseSelect = useCallback((id: string) => { const handlePhaseSelect = useCallback((id: string) => {
setSelectedPhaseId(id); setSelectedPhaseId(id);
setSelectedCommit(null); setSelectedCommit(null);
@@ -331,6 +341,7 @@ export function ReviewTab({ initiativeId }: ReviewTabProps) {
files={allFiles} files={allFiles}
comments={comments} comments={comments}
onFileClick={handleFileClick} onFileClick={handleFileClick}
onCommentClick={handleCommentClick}
selectedCommit={selectedCommit} selectedCommit={selectedCommit}
activeFiles={files} activeFiles={files}
commits={commits} commits={commits}