From a2c0963c93a887119a193dced596d5efdac4c3c0 Mon Sep 17 00:00:00 2001 From: brennanb2025 Date: Tue, 12 May 2026 14:55:54 -0700 Subject: [PATCH] fix(activity): make event row the click target for navigate + ack The inline "Jump to agent" button only rendered when agentAlive was true, so retained-done rows had no jump affordance, and in compact mode it was hover-only. Users naturally click anywhere on the row expecting it to navigate. Move the navigate-and-ack logic onto the row's onClick (with role, tabIndex, and Enter/Space keyboard support) and drop the inline buttons. Per the design doc (option 1), drop the agentAlive gate entirely: activateAndRevealWorktree is safe unconditionally and activateTabAndFocusPane silently no-ops on a missing tab id, so a stale-tab click is a soft no-op. Mirror the same pattern on WorktreeEventRow so clicking a "Worktree created" row navigates to that worktree. Co-authored-by: Orca --- .../activity/ActivityPrototypePage.tsx | 63 ++++++++++++------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/src/renderer/src/components/activity/ActivityPrototypePage.tsx b/src/renderer/src/components/activity/ActivityPrototypePage.tsx index 7d86420806b..cdff7cd3b17 100644 --- a/src/renderer/src/components/activity/ActivityPrototypePage.tsx +++ b/src/renderer/src/components/activity/ActivityPrototypePage.tsx @@ -320,8 +320,16 @@ function AgentEventRow({ const compact = density === 'compact' const dotState = asDotState(event.state) - const jumpToAgent = (clickEvent: React.MouseEvent): void => { - clickEvent.stopPropagation() + // Why (row click = navigate + ack): the inline "Jump to agent" button only + // rendered when agentAlive (so retained-done rows had no jump affordance at + // all) and in compact mode it was hover-only. Users naturally click anywhere + // on the row expecting it to navigate, so the row itself takes over the + // navigate role and subsumes the button. Per the design doc we drop the + // agentAlive gate entirely (option 1): activateAndRevealWorktree is safe + // unconditionally and activateTabAndFocusPane silently no-ops on a missing + // tab id, so a stale-tab click is just a soft no-op. + const openAgent = (clickEvent?: React.MouseEvent | React.KeyboardEvent): void => { + clickEvent?.stopPropagation() onMarkRead(event) activateAndRevealWorktree(event.worktree.id) activateTabAndFocusPane(event.tab.id, paneIdFromPaneKey(event.entry.paneKey)) @@ -329,12 +337,20 @@ function AgentEventRow({ return (
{ + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault() + openAgent(e) + } + }} className={cn( - 'group grid grid-cols-[2rem_minmax(0,1fr)_7.25rem] gap-3 border-b border-border px-3 transition-colors hover:bg-accent/40', + 'group grid grid-cols-[2rem_minmax(0,1fr)_7.25rem] gap-3 border-b border-border px-3 cursor-pointer transition-colors hover:bg-accent/40', compact ? 'py-2' : 'py-3.5', event.unread && 'bg-accent/20' )} - onClick={() => onMarkRead(event)} >
@@ -392,28 +408,10 @@ function AgentEventRow({ {agentMeta(event)}
- {!compact && event.agentAlive ? ( -
- -
- ) : null}
- {compact && event.agentAlive ? ( - - ) : null}
) @@ -430,14 +428,31 @@ function WorktreeEventRow({ }): React.JSX.Element { const compact = density === 'compact' + // Why: mirror AgentEventRow — clicking a "Worktree created" row should + // navigate to that worktree (and ack the unread). The row is the click + // target; there's no separate jump button. + const openWorktree = (clickEvent?: React.MouseEvent | React.KeyboardEvent): void => { + clickEvent?.stopPropagation() + onMarkRead(event) + activateAndRevealWorktree(event.worktree.id) + } + return (
{ + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault() + openWorktree(e) + } + }} className={cn( - 'group grid grid-cols-[2rem_minmax(0,1fr)_7.25rem] gap-3 border-b border-border px-3 transition-colors hover:bg-accent/40', + 'group grid grid-cols-[2rem_minmax(0,1fr)_7.25rem] gap-3 border-b border-border px-3 cursor-pointer transition-colors hover:bg-accent/40', compact ? 'py-2' : 'py-3.5', event.unread && 'bg-accent/20' )} - onClick={() => onMarkRead(event)} >