From fe8b60b11c4cbe987fe70b2749742d0468aab878 Mon Sep 17 00:00:00 2001
From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Date: Thu, 18 Jun 2026 16:17:28 -0700
Subject: [PATCH] Show branch cues in experimental worktree cards (#5737)
---
.../src/components/sidebar/WorktreeCard.tsx | 1 +
.../sidebar/WorktreeCardStatusSlot.test.tsx | 51 +++++++++++++++++--
.../sidebar/WorktreeCardStatusSlot.tsx | 49 ++++++++++++++++--
src/renderer/src/i18n/locales/en.json | 1 +
src/renderer/src/i18n/locales/es.json | 1 +
src/renderer/src/i18n/locales/ja.json | 3 +-
src/renderer/src/i18n/locales/ko.json | 3 +-
src/renderer/src/i18n/locales/zh.json | 3 +-
8 files changed, 102 insertions(+), 10 deletions(-)
diff --git a/src/renderer/src/components/sidebar/WorktreeCard.tsx b/src/renderer/src/components/sidebar/WorktreeCard.tsx
index 454367f3b..dbb74f9e7 100644
--- a/src/renderer/src/components/sidebar/WorktreeCard.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeCard.tsx
@@ -1209,6 +1209,7 @@ const WorktreeCard = React.memo(function WorktreeCard({
onToggleUnread={handleToggleUnreadQuick}
prDisplay={hoverReview}
newCardStyle={newCardStyle}
+ hasBranchIdentity={!isFolder && branch.length > 0}
/>
) : null}
diff --git a/src/renderer/src/components/sidebar/WorktreeCardStatusSlot.test.tsx b/src/renderer/src/components/sidebar/WorktreeCardStatusSlot.test.tsx
index 1bc33db2c..d916b12e5 100644
--- a/src/renderer/src/components/sidebar/WorktreeCardStatusSlot.test.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeCardStatusSlot.test.tsx
@@ -148,6 +148,46 @@ describe('WorktreeCardStatusSlot', () => {
expect(markup).not.toContain('bg-neutral-500/40')
})
+ it('uses a branch icon instead of the quiet active dot when new card style has no review', () => {
+ const markup = renderToStaticMarkup(
+
+ )
+
+ expect(markup).toContain('Branch')
+ expect(markup).toContain('lucide-git-branch')
+ expect(markup).toContain('text-muted-foreground/70')
+ expect(markup).not.toContain('bg-emerald-500')
+ })
+
+ it('keeps the quiet dot when the row has no branch identity', () => {
+ const markup = renderToStaticMarkup(
+
+ )
+
+ expect(markup).toContain('Active')
+ expect(markup).toContain('bg-emerald-500')
+ expect(markup).not.toContain('lucide-git-branch')
+ })
+
it('keeps working activity ahead of PR status in new card style', () => {
mocks.status = 'working'
const markup = renderToStaticMarkup(
@@ -237,23 +277,26 @@ describe('WorktreeCardStatusSlot', () => {
expect(markup).not.toContain('bg-emerald-500')
})
- it('keeps the new style unread status dot in the stable lane footprint', () => {
+ it('overlays unread on the no-review branch icon in new card style', () => {
const markup = renderToStaticMarkup(
)
- expect(markup).toContain('Active · Mark as unread')
+ expect(markup).toContain('Branch · Mark as read')
expect(markup).toContain(
'group/unread relative flex cursor-pointer items-center justify-center rounded transition-all size-5'
)
+ expect(markup).toContain('lucide-git-branch')
+ expect(markup).toContain('absolute -right-1 -top-1 size-[13px] text-amber-500')
+ expect(markup).not.toContain('bg-emerald-500')
})
})
diff --git a/src/renderer/src/components/sidebar/WorktreeCardStatusSlot.tsx b/src/renderer/src/components/sidebar/WorktreeCardStatusSlot.tsx
index 82b6fd2f2..e15a41cda 100644
--- a/src/renderer/src/components/sidebar/WorktreeCardStatusSlot.tsx
+++ b/src/renderer/src/components/sidebar/WorktreeCardStatusSlot.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import { Bell } from 'lucide-react'
+import { Bell, GitBranch } from 'lucide-react'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { cn } from '@/lib/utils'
import { getWorktreeStatusLabel, type WorktreeStatus } from '@/lib/worktree-status'
@@ -19,10 +19,15 @@ type WorktreeCardStatusSlotProps = {
onPointerDown: React.PointerEventHandler
prDisplay?: WorktreeCardPrDisplay | null
newCardStyle?: boolean
+ hasBranchIdentity?: boolean
className?: string
}
const QUIET_REVIEW_REPLACEABLE_STATUSES = new Set(['active', 'done', 'inactive'])
+// Why: a missing review display can also mean provider state is unavailable,
+// so the passive label names the branch cue without claiming no review exists.
+const BRANCH_STATUS_LABEL = 'Branch'
+const branchStatusIconClassName = 'size-4 text-muted-foreground/70'
function getReviewStatusTooltip(review: WorktreeCardPrDisplay): string {
const label = getReviewLabel(review)
@@ -57,6 +62,7 @@ export function WorktreeCardStatusSlot({
onPointerDown,
prDisplay = null,
newCardStyle = false,
+ hasBranchIdentity = true,
className
}: WorktreeCardStatusSlotProps): React.JSX.Element | null {
const status = useWorktreeActivityStatus(worktreeId)
@@ -66,9 +72,20 @@ export function WorktreeCardStatusSlot({
showStatus &&
prDisplay !== null &&
QUIET_REVIEW_REPLACEABLE_STATUSES.has(status)
+ const canShowBranchStatus =
+ newCardStyle &&
+ showStatus &&
+ hasBranchIdentity &&
+ prDisplay === null &&
+ QUIET_REVIEW_REPLACEABLE_STATUSES.has(status)
const passiveStatusLabel =
- canShowReviewStatus && prDisplay ? getReviewStatusTooltip(prDisplay) : statusLabel
+ canShowReviewStatus && prDisplay
+ ? getReviewStatusTooltip(prDisplay)
+ : canShowBranchStatus
+ ? BRANCH_STATUS_LABEL
+ : statusLabel
const reviewStatusIconClassName = 'size-4'
+ const branchStatusIcon =
const passiveStatus =
canShowReviewStatus && prDisplay ? (
@@ -82,6 +99,18 @@ export function WorktreeCardStatusSlot({
{passiveStatusLabel}
+ ) : canShowBranchStatus ? (
+
+
+
+ {branchStatusIcon}
+ {passiveStatusLabel}
+
+
+
+ {passiveStatusLabel}
+
+
) : newCardStyle && showStatus ? (
<>
@@ -106,7 +135,7 @@ export function WorktreeCardStatusSlot({
const actionLabel = isUnread ? 'Mark as read' : 'Mark as unread'
const tooltip =
- showStatus && (!isUnread || (newCardStyle && canShowReviewStatus && prDisplay))
+ showStatus && (!isUnread || (newCardStyle && (canShowBranchStatus || canShowReviewStatus)))
? `${passiveStatusLabel} · ${unreadTooltip}`
: unreadTooltip
@@ -135,6 +164,13 @@ export function WorktreeCardStatusSlot({
>
+ ) : isUnread && showStatus && canShowBranchStatus ? (
+ <>
+
+ {branchStatusIcon}
+
+
+ >
) : isUnread ? (
) : showStatus && canShowReviewStatus && prDisplay ? (
@@ -144,6 +180,13 @@ export function WorktreeCardStatusSlot({
>
+ ) : showStatus && canShowBranchStatus ? (
+ <>
+
+ {branchStatusIcon}
+
+
+ >
) : showStatus ? (
<>