From 6b3d8cf2f17e559f2e644ce3e722c9ceba906ac6 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Fri, 31 Jul 2026 23:00:57 -0500 Subject: [PATCH] fix(desktop): open the review pane from the branch and diff counts only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The composer's coding strip made the whole bar a button, so a click anywhere along it — including the dead space between the branch and the counts — opened the review pane. Only the two things that name the diff are clickable now: the branch glyph + label, and the ahead/behind + ±lines cluster. The strip itself is inert and no longer paints a hover state. --- .../composer/status-stack/coding-row.test.tsx | 46 ++++++++++ .../chat/composer/status-stack/coding-row.tsx | 87 +++++++++---------- 2 files changed, 88 insertions(+), 45 deletions(-) create mode 100644 apps/desktop/src/app/chat/composer/status-stack/coding-row.test.tsx diff --git a/apps/desktop/src/app/chat/composer/status-stack/coding-row.test.tsx b/apps/desktop/src/app/chat/composer/status-stack/coding-row.test.tsx new file mode 100644 index 0000000000000..9d10dd9c96fec --- /dev/null +++ b/apps/desktop/src/app/chat/composer/status-stack/coding-row.test.tsx @@ -0,0 +1,46 @@ +import { cleanup, fireEvent, render, screen } from '@testing-library/react' +import { atom } from 'nanostores' +import { afterEach, describe, expect, it, vi } from 'vitest' + +vi.mock('@/store/coding-status', () => ({ + registerRepoStatusCwd: () => undefined, + repoStatusForCwd: () => + atom({ + added: 12, + ahead: 0, + behind: 0, + branch: 'bb/hitbox', + defaultBranch: 'main', + detached: false, + removed: 3, + untracked: 0 + }), + repoWorktreesForCwd: () => atom([]) +})) + +const { CodingStatusRow } = await import('./coding-row') + +describe('CodingStatusRow', () => { + afterEach(() => { + cleanup() + }) + + it('opens the review pane from the branch and the diff counts, never the bar itself', () => { + const onOpen = vi.fn() + + const { container } = render() + + const bar = container.querySelector('.coding-status-bar') + + expect(bar).not.toBeNull() + + fireEvent.click(bar!) + expect(onOpen).not.toHaveBeenCalled() + + fireEvent.click(screen.getByText('bb/hitbox')) + expect(onOpen).toHaveBeenCalledTimes(1) + + fireEvent.click(screen.getByText('12').closest('button')!) + expect(onOpen).toHaveBeenCalledTimes(2) + }) +}) diff --git a/apps/desktop/src/app/chat/composer/status-stack/coding-row.tsx b/apps/desktop/src/app/chat/composer/status-stack/coding-row.tsx index c4b1a56956cf5..ca51f842ff7a6 100644 --- a/apps/desktop/src/app/chat/composer/status-stack/coding-row.tsx +++ b/apps/desktop/src/app/chat/composer/status-stack/coding-row.tsx @@ -215,20 +215,25 @@ export const CodingStatusRow = memo(function CodingStatusRow({ // The base "where am I working" strip is part of the composer surface // itself, so it inherits the composer's width and clipped top radius. className="coding-status-bar min-h-7 rounded-t-[inherit] rounded-b-none border-b border-(--ui-stroke-tertiary) px-3.5 py-1.5 hover:bg-transparent" - // Static branch glyph — never the loading spinner. This row only renders - // once `status` exists, so a spinner here only ever fired on *refreshes* - // of an already-loaded repo (window focus, turn settle), reading as an - // annoying icon "blip" with no first-load value. Refreshes are silent. - leading={} - onActivate={onOpen} >
- - {branchLabel} - + + + + {branchLabel} + {/* Branch actions kebab — same pattern as the session/worktree rows. ALWAYS laid out; only its opacity flips on hover/focus/open, so @@ -246,14 +251,6 @@ export const CodingStatusRow = memo(function CodingStatusRow({
- {(status.ahead > 0 || status.behind > 0) && ( - - {status.ahead > 0 && ( - - - {status.ahead} + {/* The other half of the hit target: the counts describe what's in the + review pane, so clicking them opens it. */} + {(status.ahead > 0 || status.behind > 0 || hasLineDelta || untrackedOnly) && ( + + )}