From 54a4f784a4afec38c933bb7c0f9adc1d92fece93 Mon Sep 17 00:00:00 2001 From: Dotta Date: Fri, 6 Mar 2026 14:27:12 -0600 Subject: [PATCH] fix(ui): clickable unread dot in inbox with fade-out, remove empty circle for read issues In the My Recent Issues section, the blue unread dot is now a button that marks the issue as read on click with a smooth opacity fade-out. Already-read issues show empty space instead of a hollow circle. Co-Authored-By: Claude Opus 4.6 --- ui/src/pages/Inbox.tsx | 101 +++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 29 deletions(-) diff --git a/ui/src/pages/Inbox.tsx b/ui/src/pages/Inbox.tsx index 194e13ef..f3cefdd0 100644 --- a/ui/src/pages/Inbox.tsx +++ b/ui/src/pages/Inbox.tsx @@ -498,6 +498,31 @@ export function Inbox() { }, }); + const [fadingOutIssues, setFadingOutIssues] = useState>(new Set()); + + const markReadMutation = useMutation({ + mutationFn: (id: string) => issuesApi.markRead(id), + onMutate: (id) => { + setFadingOutIssues((prev) => new Set(prev).add(id)); + }, + onSuccess: () => { + if (selectedCompanyId) { + queryClient.invalidateQueries({ queryKey: queryKeys.issues.listTouchedByMe(selectedCompanyId) }); + queryClient.invalidateQueries({ queryKey: queryKeys.issues.listUnreadTouchedByMe(selectedCompanyId) }); + queryClient.invalidateQueries({ queryKey: queryKeys.sidebarBadges(selectedCompanyId) }); + } + }, + onSettled: (_data, _error, id) => { + setTimeout(() => { + setFadingOutIssues((prev) => { + const next = new Set(prev); + next.delete(id); + return next; + }); + }, 300); + }, + }); + if (!selectedCompanyId) { return ; } @@ -867,35 +892,53 @@ export function Inbox() { My Recent Issues
- {touchedIssues.map((issue) => ( - - - - - - - - {issue.identifier ?? issue.id.slice(0, 8)} - - {issue.title} - - {issue.lastExternalCommentAt - ? `commented ${timeAgo(issue.lastExternalCommentAt)}` - : `updated ${timeAgo(issue.updatedAt)}`} - - - ))} + {touchedIssues.map((issue) => { + const isUnread = issue.isUnreadForMe && !fadingOutIssues.has(issue.id); + const isFading = fadingOutIssues.has(issue.id); + return ( +
+ + {(isUnread || isFading) && ( + + )} + + + + + + {issue.identifier ?? issue.id.slice(0, 8)} + + {issue.title} + + {issue.lastExternalCommentAt + ? `commented ${timeAgo(issue.lastExternalCommentAt)}` + : `updated ${timeAgo(issue.updatedAt)}`} + + +
+ ); + })}