From a1efdedb2afb4647615516098ca32d009a6e07d8 Mon Sep 17 00:00:00 2001 From: Hiren Kangad Date: Thu, 12 Mar 2026 18:47:57 +0530 Subject: [PATCH] feat(review): add focused thread highlight and headerSlot to ThreadList - FOCUSED_BG and FOCUSED_BORDER tokens in feedbackStyles - headerSlot prop for draft pin comment input above thread list - focusedThreadId prop highlights active thread row with accent border - ThreadListItem gains focused prop with left border + subtle background --- frontend/src/components/feedback/ThreadList.tsx | 10 ++++++++++ frontend/src/components/feedback/ThreadListItem.tsx | 11 ++++++++--- frontend/src/components/feedback/feedbackStyles.ts | 2 ++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/feedback/ThreadList.tsx b/frontend/src/components/feedback/ThreadList.tsx index 7b250b4..3a66855 100644 --- a/frontend/src/components/feedback/ThreadList.tsx +++ b/frontend/src/components/feedback/ThreadList.tsx @@ -29,6 +29,10 @@ interface ThreadListProps { newCommentText: string; onNewCommentChange: (text: string) => void; onCreateThread: () => void; + /** Optional slot rendered above the thread list (e.g., draft pin input) */ + headerSlot?: React.ReactNode; + /** Currently focused thread ID for highlighting */ + focusedThreadId?: string | null; } export default function ThreadList({ @@ -45,6 +49,8 @@ export default function ThreadList({ newCommentText, onNewCommentChange, onCreateThread, + headerSlot, + focusedThreadId, }: ThreadListProps) { const [showOrphans, setShowOrphans] = React.useState(false); @@ -154,6 +160,9 @@ export default function ThreadList({ )} + {/* Draft pin comment input (injected from FeedbackPanel) */} + {headerSlot} + {/* Thread list */}
{threads.length === 0 && ( @@ -181,6 +190,7 @@ export default function ThreadList({ thread={t} pinNumber={store.getPinNumber(t.id)} onClick={() => onSelectThread(t.id)} + focused={focusedThreadId === t.id} /> ))} diff --git a/frontend/src/components/feedback/ThreadListItem.tsx b/frontend/src/components/feedback/ThreadListItem.tsx index bc26bcd..2463d22 100644 --- a/frontend/src/components/feedback/ThreadListItem.tsx +++ b/frontend/src/components/feedback/ThreadListItem.tsx @@ -10,15 +10,18 @@ import { STATUS_RESOLVED, BORDER, HOVER_BG, + FOCUSED_BG, + ACCENT, } from './feedbackStyles'; interface ThreadListItemProps { thread: Thread; pinNumber: number; onClick: () => void; + focused?: boolean; } -export default function ThreadListItem({ thread, pinNumber, onClick }: ThreadListItemProps) { +export default function ThreadListItem({ thread, pinNumber, onClick, focused }: ThreadListItemProps) { const firstComment = thread.comments[0]; const isResolved = thread.status === 'resolved'; @@ -30,9 +33,11 @@ export default function ThreadListItem({ thread, pinNumber, onClick }: ThreadLis borderBottom: `1px solid ${BORDER}`, cursor: 'pointer', transition: 'background 0.1s ease', + background: focused ? FOCUSED_BG : 'transparent', + borderLeft: focused ? `2px solid ${ACCENT}` : '2px solid transparent', }} - onMouseEnter={(e) => (e.currentTarget.style.background = HOVER_BG)} - onMouseLeave={(e) => (e.currentTarget.style.background = 'transparent')} + onMouseEnter={(e) => { if (!focused) e.currentTarget.style.background = HOVER_BG; }} + onMouseLeave={(e) => { if (!focused) e.currentTarget.style.background = 'transparent'; }} > {/* Row 1: author circle + name + timestamp */}
diff --git a/frontend/src/components/feedback/feedbackStyles.ts b/frontend/src/components/feedback/feedbackStyles.ts index 8b84b9c..eb0f821 100644 --- a/frontend/src/components/feedback/feedbackStyles.ts +++ b/frontend/src/components/feedback/feedbackStyles.ts @@ -17,6 +17,8 @@ export const INPUT_BORDER = '#26262c'; export const INPUT_BORDER_FOCUS = '#4a9eff44'; export const HOVER_BG = '#16161a'; export const FILTER_ACTIVE_BG = '#1e1e24'; +export const FOCUSED_BG = 'rgba(74, 158, 255, 0.06)'; +export const FOCUSED_BORDER = 'rgba(74, 158, 255, 0.2)'; // Shared panel container style export const panelContainerStyle: React.CSSProperties = {