Revert #12793: put PR status back in the left status lane

#12793 fixed PR status being hidden by workspace activity by relocating
it: prDisplay was dropped from WorktreeCardStatusSlot and re-rendered as
WorktreeCardReviewStatus in the title-row indicator group, at the right
edge of the card.

Reverting restores the review glyph to the left status lane. Because
#12658 still narrows the passive-identity set to {inactive}, this alone
brings PR status back only for inactive workspaces; reverting #12658
widens it to active and done.

No behavior change for branch identity, and #8813's guard stays intact.
This commit is contained in:
Brennan Benson
2026-08-05 19:26:22 -07:00
parent 211b2d1a35
commit 5a46791fb4
6 changed files with 273 additions and 165 deletions
@@ -24,7 +24,6 @@ let issueCache: Record<string, unknown> = {}
let prCache: Record<string, unknown> = {}
let workspacePortScan: WorkspacePortScanResult | null = null
let settings: Partial<GlobalSettings> | null = null
let activityStatus = 'inactive'
vi.mock('@/store', () => ({
useAppStore: (selector: (state: unknown) => unknown) =>
@@ -61,7 +60,7 @@ vi.mock('@/components/ui/tooltip', () => ({
}))
vi.mock('./use-worktree-activity-status', () => ({
useWorktreeActivityStatus: () => activityStatus
useWorktreeActivityStatus: () => 'inactive'
}))
vi.mock('./CacheTimer', () => ({
@@ -163,7 +162,6 @@ describe('WorktreeCard linked PR display', () => {
prCache = {}
workspacePortScan = null
settings = null
activityStatus = 'inactive'
})
it('keeps linked GH PR status out of the left status slot by default', async () => {
@@ -231,10 +229,11 @@ describe('WorktreeCard linked PR display', () => {
)
expect(unreadMarkup).not.toContain('aria-label="Mark as read"')
expect(unreadMarkup).toContain('Inactive · Unread')
expect(unreadMarkup).toContain('PR checks: Failed')
expect(unreadMarkup).toContain('PR checks: Failed · Unread')
expect(unreadMarkup).not.toContain('Mark read')
expect(unreadMarkup).toContain('size-[13px]')
expect(unreadMarkup).toContain('size-[13px] translate-x-px')
expect(unreadMarkup).not.toContain('lucide-bell')
expect(unreadMarkup).not.toContain('text-amber-500')
expect(unreadMarkup).toContain('data-worktree-status-lane-unread=""')
expect(unreadMarkup).toContain('data-worktree-unread-alert=""')
expect(unreadMarkup).toContain('bg-amber-500')
@@ -242,7 +241,7 @@ describe('WorktreeCard linked PR display', () => {
expect(getInlineRenameTitleTag(readMarkup)).toContain('font-normal text-foreground/80')
}, 20_000)
it('shows linked GH PR status in the title row before hosted review details are cached when new card style is on', async () => {
it('shows linked GH PR status in the left status slot before hosted review details are cached when new card style is on', async () => {
settings = { experimentalNewWorktreeCardStyle: true }
const { default: WorktreeCard } = await import('./WorktreeCard')
@@ -630,10 +629,9 @@ describe('WorktreeCard linked PR display', () => {
expect(markup).not.toContain('58941')
})
it('renders activity and linked PR status in independent sidebar lanes', async () => {
it('renders linked PR status in the left status slot instead of the right metadata list', async () => {
settings = { experimentalNewWorktreeCardStyle: true }
worktreeCardProperties = ['status']
activityStatus = 'active'
hostedReviewCache = {
'local::repo-1::feature/local-branch': {
data: makeHostedReview({ status: 'failure' }),
@@ -647,13 +645,12 @@ describe('WorktreeCard linked PR display', () => {
)
expect(markup).toContain('PR checks: Failed')
expect(markup).toContain('Active')
expect(markup).toContain('bg-emerald-500')
expect(markup).toContain('data-worktree-card-review-status=""')
expect(markup).toContain('text-rose-500/85')
expect(markup).not.toContain('Linked PR #456')
expect(markup).not.toContain('CI checks')
})
it('uses branch PR cache for the title-row status before hosted-review metadata warms', async () => {
it('uses branch PR cache for the status slot before hosted-review metadata warms', async () => {
settings = { experimentalNewWorktreeCardStyle: true }
worktreeCardProperties = ['status']
prCache = {
@@ -26,7 +26,6 @@ import { LinearAgentSkillSetupPrompt } from './LinearAgentSkillSetupPrompt'
import WorktreeCardAgents from './WorktreeCardAgents'
import { useWorktreeAgentRows } from './useWorktreeAgentRows'
import { WorktreeCardStatusSlot } from './WorktreeCardStatusSlot'
import { WorktreeCardReviewStatus } from './WorktreeCardReviewStatus'
import { cn } from '@/lib/utils'
import { WorktreeCardSshHostControl } from './WorktreeCardSshHostControl'
import { activateWorktreeFromSidebar } from '@/lib/sidebar-worktree-activation'
@@ -1208,13 +1207,11 @@ const WorktreeCard = React.memo(function WorktreeCard({
!!conflictOperation && conflictOperation !== 'unknown' && conflictOperation !== 'rebase'
const hasMetadataBadge = showConflictOperationBadge
const showUnreadQuickAction = !affiliateListMode && showStatus && !newCardStyle
// Why: the slot owns activity and unread; review/check state has its own title-row indicator.
// Why: the slot owns the unread/status lane; legacy keeps the bell toggle, the new card keeps the glyph passive.
const showCombinedStatusSlot = showStatus
const showReviewStatus = newCardStyle && showStatus && statusLaneReview !== null
const showTitleRowPrimary = compactCards && worktree.isMainWorktree && !isFolder
const showMetaRowDetails = !newCardStyle && !compactCards && (hasDetails || hasPorts)
const showTitleRowIndicators =
(newCardStyle || compactCards) && (hasDetails || hasPorts || showReviewStatus)
const showTitleRowIndicators = (newCardStyle || compactCards) && (hasDetails || hasPorts)
// Why: grouped views can hide the repo badge; don't reserve a blank metadata lane unless there's real content.
const hasDetailedMetaRowContent = Boolean(
(showRepoBadgeInMetaRow && repo) ||
@@ -1373,12 +1370,7 @@ const WorktreeCard = React.memo(function WorktreeCard({
detailsAndPortsContent
)
const titleRowIndicators = showTitleRowIndicators ? (
<div className="ml-auto flex shrink-0 items-center gap-1 pr-1.5">
{showReviewStatus && statusLaneReview ? (
<WorktreeCardReviewStatus review={statusLaneReview} />
) : null}
{detailsAndPorts}
</div>
<div className="ml-auto flex shrink-0 items-center gap-1 pr-1.5">{detailsAndPorts}</div>
) : null
const hasSecondaryCardContent =
hasMetaRow || !!remoteBranchConflict || showInlineAgentList || showLineageChildChip
@@ -1412,6 +1404,7 @@ const WorktreeCard = React.memo(function WorktreeCard({
unreadTooltip={unreadTooltip}
onPointerDown={stopQuickActionPointerPropagation}
onToggleUnread={handleToggleUnreadQuick}
prDisplay={statusLaneReview}
newCardStyle={newCardStyle}
hasBranchIdentity={hasPathIdentityEnabled && Boolean(branchIdentityDisplay)}
/>
@@ -1,53 +0,0 @@
import { renderToStaticMarkup } from 'react-dom/server'
import type { ReactNode } from 'react'
import { describe, expect, it, vi } from 'vitest'
import { WorktreeCardReviewStatus } from './WorktreeCardReviewStatus'
import type { WorktreeCardPrDisplay } from './worktree-card-pr-display'
vi.mock('@/components/ui/tooltip', () => ({
Tooltip: ({ children }: { children: ReactNode }) => <>{children}</>,
TooltipContent: ({ children }: { children: ReactNode }) => <>{children}</>,
TooltipTrigger: ({ children }: { children: ReactNode }) => <>{children}</>
}))
type ReviewOverrides = {
provider?: Exclude<WorktreeCardPrDisplay['provider'], 'unsupported'>
state?: WorktreeCardPrDisplay['state']
status?: WorktreeCardPrDisplay['status']
}
function renderReview(overrides: ReviewOverrides = {}): string {
const review: WorktreeCardPrDisplay = {
provider: 'github',
number: 123,
title: 'Review me',
state: 'open',
...overrides
}
return renderToStaticMarkup(<WorktreeCardReviewStatus review={review} />)
}
describe('WorktreeCardReviewStatus', () => {
it.each([
[{ state: 'merged' }, 'PR: Merged'],
[{ state: 'closed' }, 'PR: Closed'],
[{ state: 'draft' }, 'PR: Draft'],
[{ status: 'failure' }, 'PR checks: Failed'],
[{ status: 'pending' }, 'PR checks: Pending'],
[{ status: 'success' }, 'PR checks: Passing'],
[{}, 'PR: Open']
] as const)('describes review state %o as %s', (overrides, label) => {
expect(renderReview(overrides)).toContain(label)
})
it('uses the compact generic review glyph in its own lane', () => {
const markup = renderReview({ provider: 'gitlab', status: 'pending' })
expect(markup).toContain('data-worktree-card-review-status=""')
expect(markup).toContain('MR checks: Pending')
expect(markup).toContain('viewBox="0 0 16 16"')
expect(markup).toContain('size-[13px]')
expect(markup).toContain('text-amber-500/85')
expect(markup).not.toContain('lucide-git-merge')
})
})
@@ -1,52 +0,0 @@
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import type { WorktreeCardPrDisplay } from './worktree-card-pr-display'
import { getReviewLabel, ReviewIcon } from './worktree-review-helpers'
type WorktreeCardReviewStatusProps = {
review: WorktreeCardPrDisplay
}
function getReviewStatusTooltip(review: WorktreeCardPrDisplay): string {
const label = getReviewLabel(review)
if (review.state === 'merged') {
return `${label}: Merged`
}
if (review.state === 'closed') {
return `${label}: Closed`
}
if (review.state === 'draft') {
return `${label}: Draft`
}
if (review.status === 'failure') {
return `${label} checks: Failed`
}
if (review.status === 'pending') {
return `${label} checks: Pending`
}
if (review.status === 'success') {
return `${label} checks: Passing`
}
return `${label}: Open`
}
export function WorktreeCardReviewStatus({
review
}: WorktreeCardReviewStatusProps): React.JSX.Element {
const tooltip = getReviewStatusTooltip(review)
return (
<Tooltip>
<TooltipTrigger asChild>
<span
data-worktree-card-review-status=""
className="inline-flex size-5 shrink-0 items-center justify-center p-0.5"
>
<ReviewIcon review={review} className="size-[13px]" variant="generic" />
<span className="sr-only">{tooltip}</span>
</span>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={8}>
<span>{tooltip}</span>
</TooltipContent>
</Tooltip>
)
}
@@ -2,6 +2,7 @@ import { renderToStaticMarkup } from 'react-dom/server'
import type { ReactNode } from 'react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { WorktreeCardStatusSlot } from './WorktreeCardStatusSlot'
import type { WorktreeCardPrDisplay } from './worktree-card-pr-display'
const mocks = vi.hoisted(() => ({
status: 'active'
@@ -22,6 +23,21 @@ describe('WorktreeCardStatusSlot', () => {
mocks.status = 'active'
})
const review: WorktreeCardPrDisplay = {
provider: 'github',
number: 123,
title: 'Review me',
state: 'open',
status: 'failure'
}
const gitlabReview: WorktreeCardPrDisplay = {
provider: 'gitlab',
number: 456,
title: 'Review me',
state: 'open',
status: 'pending'
}
it('lets the unread bell replace the visual status dot by default', () => {
const markup = renderToStaticMarkup(
<WorktreeCardStatusSlot
@@ -157,6 +173,46 @@ describe('WorktreeCardStatusSlot', () => {
expect(markup).toContain('bg-emerald-500')
})
it('keeps the quiet active dot ahead of PR status by default', () => {
const markup = renderToStaticMarkup(
<WorktreeCardStatusSlot
worktreeId="wt-1"
showStatus
showUnreadAction={false}
isUnread={false}
unreadTooltip="Mark as unread"
onPointerDown={vi.fn()}
onToggleUnread={vi.fn()}
prDisplay={review}
/>
)
expect(markup).toContain('Active')
expect(markup).toContain('bg-emerald-500')
expect(markup).not.toContain('PR checks: Failed')
})
it('keeps the active dot ahead of PR status when new card style is on', () => {
const markup = renderToStaticMarkup(
<WorktreeCardStatusSlot
worktreeId="wt-1"
showStatus
showUnreadAction={false}
isUnread={false}
unreadTooltip="Mark as unread"
onPointerDown={vi.fn()}
onToggleUnread={vi.fn()}
prDisplay={review}
newCardStyle
/>
)
expect(markup).toContain('Active')
expect(markup).toContain('inline-flex size-5 items-center justify-center')
expect(markup).toContain('bg-emerald-500')
expect(markup).not.toContain('PR checks: Failed')
})
it('keeps the emerald activity dot ahead of branch identity when new card style is on', () => {
const markup = renderToStaticMarkup(
<WorktreeCardStatusSlot
@@ -177,7 +233,30 @@ describe('WorktreeCardStatusSlot', () => {
expect(markup).not.toContain('lucide-git-branch')
})
it('shows done activity in new card style', () => {
it('uses the unified compact review glyph for GitLab MR status', () => {
mocks.status = 'inactive'
const markup = renderToStaticMarkup(
<WorktreeCardStatusSlot
worktreeId="wt-1"
showStatus
showUnreadAction={false}
isUnread={false}
unreadTooltip="Mark as unread"
onPointerDown={vi.fn()}
onToggleUnread={vi.fn()}
prDisplay={gitlabReview}
newCardStyle
/>
)
expect(markup).toContain('MR checks: Pending')
expect(markup).toContain('viewBox="0 0 16 16"')
expect(markup).toContain('size-[13px] translate-x-px')
expect(markup).toContain('text-amber-500/85')
expect(markup).not.toContain('lucide-git-merge')
})
it('keeps the done dot ahead of PR status when new card style is on', () => {
mocks.status = 'done'
const markup = renderToStaticMarkup(
<WorktreeCardStatusSlot
@@ -188,12 +267,35 @@ describe('WorktreeCardStatusSlot', () => {
unreadTooltip="Mark as unread"
onPointerDown={vi.fn()}
onToggleUnread={vi.fn()}
prDisplay={review}
newCardStyle
/>
)
expect(markup).toContain('Done')
expect(markup).toContain('bg-emerald-500')
expect(markup).not.toContain('PR checks: Failed')
})
it('uses PR status instead of the inactive dot when new card style is on', () => {
mocks.status = 'inactive'
const markup = renderToStaticMarkup(
<WorktreeCardStatusSlot
worktreeId="wt-1"
showStatus
showUnreadAction={false}
isUnread={false}
unreadTooltip="Mark as unread"
onPointerDown={vi.fn()}
onToggleUnread={vi.fn()}
prDisplay={review}
newCardStyle
/>
)
expect(markup).toContain('PR checks: Failed')
expect(markup).toContain('text-rose-500/85')
expect(markup).not.toContain('bg-neutral-500/40')
})
it('uses a branch icon with branch-only tooltip copy on quiet rows', () => {
@@ -261,7 +363,7 @@ describe('WorktreeCardStatusSlot', () => {
expect(markup).not.toContain('lucide-git-branch')
})
it('shows working activity in new card style', () => {
it('keeps working activity ahead of PR status in new card style', () => {
mocks.status = 'working'
const markup = renderToStaticMarkup(
<WorktreeCardStatusSlot
@@ -272,6 +374,7 @@ describe('WorktreeCardStatusSlot', () => {
unreadTooltip="Mark as unread"
onPointerDown={vi.fn()}
onToggleUnread={vi.fn()}
prDisplay={review}
newCardStyle
/>
)
@@ -279,9 +382,10 @@ describe('WorktreeCardStatusSlot', () => {
expect(markup).toContain('Working')
expect(markup).toContain('inline-flex size-5 items-center justify-center')
expect(markup).toContain('border-yellow-500')
expect(markup).not.toContain('PR checks: Failed')
})
it('shows permission activity in new card style', () => {
it('keeps permission activity ahead of PR status in new card style', () => {
mocks.status = 'permission'
const markup = renderToStaticMarkup(
<WorktreeCardStatusSlot
@@ -292,6 +396,7 @@ describe('WorktreeCardStatusSlot', () => {
unreadTooltip="Mark as unread"
onPointerDown={vi.fn()}
onToggleUnread={vi.fn()}
prDisplay={review}
newCardStyle
/>
)
@@ -299,6 +404,59 @@ describe('WorktreeCardStatusSlot', () => {
expect(markup).toContain('Needs permission')
expect(markup).toContain('lucide-message-circle-question-mark')
expect(markup).toContain('text-amber-500')
expect(markup).not.toContain('PR checks: Failed')
})
it('keeps unread ahead of PR status by default', () => {
const markup = renderToStaticMarkup(
<WorktreeCardStatusSlot
worktreeId="wt-1"
showStatus
showUnreadAction
isUnread
unreadTooltip="Mark as read"
onPointerDown={vi.fn()}
onToggleUnread={vi.fn()}
prDisplay={review}
/>
)
expect(markup).toContain('aria-label="Mark as read"')
expect(markup).toContain('Mark as read')
expect(markup).not.toContain('Active · Mark as read')
expect(markup).not.toContain('PR checks: Failed')
expect(markup).not.toContain('bg-emerald-500')
expect(markup).toContain('text-amber-500')
})
it('overlays an unread badge on PR status when new card style is on', () => {
mocks.status = 'inactive'
const markup = renderToStaticMarkup(
<WorktreeCardStatusSlot
worktreeId="wt-1"
showStatus
showUnreadAction
isUnread
unreadTooltip="Mark as read"
onPointerDown={vi.fn()}
onToggleUnread={vi.fn()}
prDisplay={review}
newCardStyle
/>
)
expect(markup).not.toContain('aria-label="Mark as read"')
expect(markup).not.toContain('Mark as read')
expect(markup).toContain('PR checks: Failed · Unread')
expect(markup).toContain('data-worktree-status-lane-unread=""')
expect(markup).toContain('data-worktree-unread-alert=""')
expect(markup).not.toContain('group/unread')
expect(markup).not.toContain('cursor-pointer')
expect(markup).toContain('text-rose-500/85')
expect(markup).toContain('bg-amber-500')
expect(markup).not.toContain('lucide-bell')
expect(markup).not.toContain('text-amber-500')
expect(markup).not.toContain('bg-emerald-500')
})
it('overlays an unread badge on the branch icon in new card style', () => {
@@ -3,10 +3,12 @@ import { Bell, GitBranch } from 'lucide-react'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { translate } from '@/i18n/i18n'
import { cn } from '@/lib/utils'
import { getWorktreeStatusLabel } from '@/lib/worktree-status'
import { getWorktreeStatusLabel, type WorktreeStatus } from '@/lib/worktree-status'
import { FilledBellIcon } from './WorktreeCardHelpers'
import StatusIndicator from './StatusIndicator'
import { useWorktreeActivityStatus } from './use-worktree-activity-status'
import type { WorktreeCardPrDisplay } from './worktree-card-pr-display'
import { getReviewLabel, ReviewIcon } from './worktree-review-helpers'
type WorktreeCardStatusSlotProps = {
worktreeId: string
@@ -16,20 +18,24 @@ type WorktreeCardStatusSlotProps = {
unreadTooltip: string
onToggleUnread: React.MouseEventHandler<HTMLButtonElement>
onPointerDown: React.PointerEventHandler<HTMLButtonElement>
prDisplay?: WorktreeCardPrDisplay | null
newCardStyle?: boolean
hasBranchIdentity?: boolean
branchIdentityLabel?: string
className?: string
}
// Why: the passive label names the identity cue without claiming review state.
// Passive identity only replaces status when the workspace is inactive.
const IDENTITY_REPLACEABLE_STATUSES = new Set<WorktreeStatus>(['inactive'])
// Why: a missing review display can also mean provider state is unavailable,
// so the passive label names the identity cue without claiming no review exists.
function getDefaultBranchIdentityLabel(): string {
return translate('auto.components.sidebar.WorktreeCardStatusSlot.branchIdentity', 'Branch')
}
// Why: branch-style SVGs are optically left-heavy; this keeps them aligned with
// the centered activity dots in the shared status column.
const compactBranchStatusIconClassName = 'size-[13px] translate-x-px'
const branchStatusIconClassName = `${compactBranchStatusIconClassName} text-muted-foreground/70`
const compactReviewAndBranchStatusIconClassName = 'size-[13px] translate-x-px'
const branchStatusIconClassName = `${compactReviewAndBranchStatusIconClassName} text-muted-foreground/70`
// Why: a left-edge badge overlays unread on the status glyph without widening
// the lane or indenting the title; ring-sidebar cuts the dot out from busy icons.
const newCardUnreadAlertClassName =
@@ -58,6 +64,29 @@ function overlayNewCardUnreadStatus(
)
}
function getReviewStatusTooltip(review: WorktreeCardPrDisplay): string {
const label = getReviewLabel(review)
if (review.state === 'merged') {
return `${label}: Merged`
}
if (review.state === 'closed') {
return `${label}: Closed`
}
if (review.state === 'draft') {
return `${label}: Draft`
}
if (review.status === 'failure') {
return `${label} checks: Failed`
}
if (review.status === 'pending') {
return `${label} checks: Pending`
}
if (review.status === 'success') {
return `${label} checks: Passing`
}
return `${label}: Open`
}
export function WorktreeCardStatusSlot({
worktreeId,
showStatus,
@@ -66,6 +95,7 @@ export function WorktreeCardStatusSlot({
unreadTooltip,
onToggleUnread,
onPointerDown,
prDisplay = null,
newCardStyle = false,
hasBranchIdentity = false,
branchIdentityLabel,
@@ -73,43 +103,70 @@ export function WorktreeCardStatusSlot({
}: WorktreeCardStatusSlotProps): React.JSX.Element | null {
const status = useWorktreeActivityStatus(worktreeId)
const statusLabel = getWorktreeStatusLabel(status) || status
const canShowReviewStatus =
newCardStyle && showStatus && prDisplay !== null && IDENTITY_REPLACEABLE_STATUSES.has(status)
const canShowBranchStatus =
newCardStyle && showStatus && hasBranchIdentity && status === 'inactive'
const passiveStatusLabel = canShowBranchStatus
? (branchIdentityLabel ?? getDefaultBranchIdentityLabel())
: statusLabel
newCardStyle &&
showStatus &&
hasBranchIdentity &&
prDisplay === null &&
IDENTITY_REPLACEABLE_STATUSES.has(status)
const passiveStatusLabel =
canShowReviewStatus && prDisplay
? getReviewStatusTooltip(prDisplay)
: canShowBranchStatus
? (branchIdentityLabel ?? getDefaultBranchIdentityLabel())
: statusLabel
const passiveStatusTooltip =
newCardStyle && isUnread ? `${passiveStatusLabel} · Unread` : passiveStatusLabel
// Why: working and permission already own the new-card status lane, but
// unread state should still surface in tooltip/sr-only copy and reappear afterward.
const showNewCardUnreadAlert =
newCardStyle && isUnread && showStatus && status !== 'working' && status !== 'permission'
const reviewStatusIconClassName = compactReviewAndBranchStatusIconClassName
const branchStatusIcon = <GitBranch className={branchStatusIconClassName} aria-hidden="true" />
const passiveStatus = canShowBranchStatus ? (
<Tooltip>
<TooltipTrigger asChild>
<span className={cn('inline-flex size-5 items-center justify-center p-0.5', className)}>
{branchStatusIcon}
<span className="sr-only">{passiveStatusTooltip}</span>
const passiveStatus =
canShowReviewStatus && prDisplay ? (
<Tooltip>
<TooltipTrigger asChild>
<span className={cn('inline-flex size-5 items-center justify-center p-0.5', className)}>
<ReviewIcon
review={prDisplay}
className={reviewStatusIconClassName}
variant="generic"
/>
<span className="sr-only">{passiveStatusTooltip}</span>
</span>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={8}>
<span>{passiveStatusTooltip}</span>
</TooltipContent>
</Tooltip>
) : canShowBranchStatus ? (
<Tooltip>
<TooltipTrigger asChild>
<span className={cn('inline-flex size-5 items-center justify-center p-0.5', className)}>
{branchStatusIcon}
<span className="sr-only">{passiveStatusTooltip}</span>
</span>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={8}>
<span>{passiveStatusTooltip}</span>
</TooltipContent>
</Tooltip>
) : newCardStyle && showStatus ? (
<>
<span className={cn('inline-flex size-5 items-center justify-center', className)}>
<StatusIndicator status={status} aria-hidden="true" />
</span>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={8}>
<span>{passiveStatusTooltip}</span>
</TooltipContent>
</Tooltip>
) : newCardStyle && showStatus ? (
<>
<span className={cn('inline-flex size-5 items-center justify-center', className)}>
<StatusIndicator status={status} aria-hidden="true" />
</span>
<span className="sr-only">{passiveStatusTooltip}</span>
</>
) : (
<>
<StatusIndicator status={status} aria-hidden="true" className={className} />
<span className="sr-only">{statusLabel}</span>
</>
)
<span className="sr-only">{passiveStatusTooltip}</span>
</>
) : (
<>
<StatusIndicator status={status} aria-hidden="true" className={className} />
<span className="sr-only">{statusLabel}</span>
</>
)
const unreadActionEnabled = showUnreadAction && !newCardStyle
@@ -144,7 +201,15 @@ export function WorktreeCardStatusSlot({
aria-label={actionLabel}
>
{newCardStyle ? (
showStatus && canShowBranchStatus ? (
showStatus && canShowReviewStatus && prDisplay ? (
<span className="inline-flex size-5 items-center justify-center p-0.5">
<ReviewIcon
review={prDisplay}
className={reviewStatusIconClassName}
variant="generic"
/>
</span>
) : showStatus && canShowBranchStatus ? (
<span className="inline-flex size-5 items-center justify-center p-0.5">
{branchStatusIcon}
</span>