Revert "Hide branch names behind workspace card property" (#2740)

This commit is contained in:
Neil
2026-05-23 23:04:59 -07:00
committed by GitHub
parent 28ba9151a5
commit bea744b7e4
12 changed files with 29 additions and 119 deletions
-1
View File
@@ -2111,7 +2111,6 @@ describe('Store', () => {
expect(store.getUI().worktreeCardProperties).toContain('inline-agents')
expect(store.getUI().worktreeCardProperties).toContain('linear-issue')
expect(store.getUI().worktreeCardProperties).toContain('ports')
expect(store.getUI().worktreeCardProperties).not.toContain('branch')
expect(store.getUI()._inlineAgentsDefaultedForExperiment).toBe(true)
expect(store.getUI()._inlineAgentsDefaultedForAllUsers).toBe(true)
expect(store.getUI()._expandedWorktreeCardPropertiesDefaulted).toBe(true)
@@ -136,7 +136,7 @@ describe('client UI RPC methods', () => {
it('accepts persisted literal UI arrays and nested UI state', async () => {
const updated: PersistedUIState = {
...getDefaultUIState(),
worktreeCardProperties: ['status', 'branch', 'inline-agents'],
worktreeCardProperties: ['status', 'inline-agents'],
statusBarItems: ['codex'],
taskResumeState: {
githubMode: 'items',
@@ -163,7 +163,7 @@ describe('client UI RPC methods', () => {
const dispatcher = new RpcDispatcher({ runtime, methods: CLIENT_UI_METHODS })
const payload = {
worktreeCardProperties: ['status', 'branch', 'inline-agents'],
worktreeCardProperties: ['status', 'inline-agents'],
statusBarItems: ['codex'],
taskResumeState: {
githubMode: 'items',
@@ -10,7 +10,6 @@ const UnknownRecordArray = z.array(UnknownRecord)
const WorktreeCardProperty = z.enum([
'status',
'unread',
'branch',
'ci',
'issue',
'linear-issue',
@@ -35,7 +35,6 @@ const GROUP_BY_OPTIONS = [
] as const
const PROPERTY_OPTIONS: { id: WorktreeCardProperty; label: string }[] = [
{ id: 'branch', label: 'Branch name' },
{ id: 'issue', label: 'GitHub ticket' },
{ id: 'linear-issue', label: 'Linear issue' },
{ id: 'pr', label: 'PR/MR link' },
@@ -125,41 +125,6 @@ describe('WorktreeCard quick actions', () => {
expect(markup).toContain('data-workspace-board-preserve-open=""')
})
it('hides the branch name from workspace card metadata by default', () => {
const markup = renderToStaticMarkup(
<WorktreeCard
worktree={makeWorktree({
displayName: 'Visible workspace',
branch: 'refs/heads/feature/secret-ref'
})}
repo={makeRepo()}
isActive={false}
/>
)
expect(markup).toContain('Visible workspace')
expect(markup).not.toContain('feature/secret-ref')
expect(markup).not.toContain('secret-ref')
})
it('renders the branch name when the Branch name property is enabled', () => {
worktreeCardProperties = ['status', 'unread', 'branch']
const markup = renderToStaticMarkup(
<WorktreeCard
worktree={makeWorktree({
displayName: 'Visible workspace',
branch: 'refs/heads/feature/show-ref'
})}
repo={makeRepo()}
isActive={false}
/>
)
expect(markup).toContain('Visible workspace')
expect(markup).toContain('feature/show-ref')
})
it('shows delete as the top-right quick action for an inactive workspace', () => {
const markup = renderToStaticMarkup(
<WorktreeCard worktree={makeWorktree()} repo={makeRepo()} isActive={false} />
@@ -254,7 +254,6 @@ const WorktreeCard = React.memo(function WorktreeCard({
const showLinearIssue = cardProps.includes('linear-issue')
const showComment = cardProps.includes('comment')
const showPorts = cardProps.includes('ports')
const showBranch = cardProps.includes('branch')
// Skip hosted-review fetches when the corresponding card sections are hidden.
// This preference is purely presentational, so background refreshes would
@@ -416,7 +415,8 @@ const WorktreeCard = React.memo(function WorktreeCard({
)
// Why: deleting the active/current workspace or one with live activity is a
// disruptive hover action; keep the quick action delete-only and passive.
const showDeleteQuickAction = !isCurrentWorktree && !hasActiveActivity && !worktree.isMainWorktree
const showDeleteQuickAction =
!isCurrentWorktree && !hasActiveActivity && !worktree.isMainWorktree
const handleWorkspaceQuickAction = useCallback(
(event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault()
@@ -624,9 +624,10 @@ const WorktreeCard = React.memo(function WorktreeCard({
)}
{/* Why: weight alone carries the unread signal; color stays
at text-foreground in both states so the title remains
the card's primary scan target even when optional branch
metadata is hidden. */}
at text-foreground in both states so the title keeps
hierarchy against the muted branch row below (muting the
title as well flattened the card — same reasoning as the
repo chip comment below). */}
<div
className={cn(
'text-[12px] truncate leading-tight text-foreground',
@@ -642,8 +643,8 @@ const WorktreeCard = React.memo(function WorktreeCard({
{/* Why: the primary worktree (the original clone directory) cannot be
deleted via `git worktree remove`. Placing this badge next to the
name keeps that constraint visible even when branch metadata is
hidden by the user's card-property choice. */}
name makes it immediately visible and avoids confusion with the
branch name "main" shown below. */}
{worktree.isMainWorktree && !isFolder && (
<Tooltip>
<TooltipTrigger asChild>
@@ -734,11 +735,11 @@ const WorktreeCard = React.memo(function WorktreeCard({
>
{repo ? getRepoKindLabel(repo) : 'Folder'}
</Badge>
) : showBranch && branch ? (
) : (
<span className="min-w-0 text-[11px] text-muted-foreground truncate leading-none">
{branch}
</span>
) : null}
)}
{/* Why: the conflict operation (merge/rebase/cherry-pick) is the
only signal that the worktree is in an incomplete operation state.
@@ -249,23 +249,5 @@ describe('WorktreeList lineage child card renderer', () => {
expect(agentRowIndex).toBeGreaterThan(childStart)
expect(childToggleIndex).toBeGreaterThan(childStart)
expect(agentRowIndex).toBeLessThan(childToggleIndex)
expect(markup).not.toContain('child-branch')
expect(markup).not.toContain('grandchild-branch')
})
it('renders nested lineage branch labels when the Branch name property is enabled', async () => {
setLineageFixtureState()
mockStore.state.worktreeCardProperties = ['status', 'inline-agents', 'branch']
const { default: WorktreeList } = await import('./WorktreeList')
const markup = renderToStaticMarkup(
React.createElement(WorktreeList, {
scrollOffsetRef: { current: 0 },
scrollAnchorRef: { current: null }
})
)
expect(markup).toContain('child-branch')
expect(markup).toContain('grandchild-branch')
})
})
@@ -25,7 +25,6 @@ import {
useWorktreeMap
} from '@/store/selectors'
import WorktreeCard from './WorktreeCard'
import { branchDisplayName } from './WorktreeCardHelpers'
import WorktreeCardAgents from './WorktreeCardAgents'
import { SshDisconnectedDialog } from './SshDisconnectedDialog'
import { WorktreeActivityStatusIndicator } from './WorktreeActivityStatusIndicator'
@@ -126,6 +125,7 @@ import {
pruneWorktreeSelection,
updateWorktreeSelection
} from './worktree-multi-selection'
import { branchDisplayName } from './WorktreeCardHelpers'
import { callRuntimeRpc, getActiveRuntimeTarget } from '@/runtime/runtime-rpc-client'
import { getRepoHeaderCreateState } from './repo-header-create-state'
import type { PendingSidebarWorktreeReveal } from '@/store/slices/ui'
@@ -2162,10 +2162,6 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
const renderLineageChildCard = (child: WorktreeItemRow) => {
const isActive = activeWorktreeId === child.worktree.id
const childRepo = child.repo
const showChildRepoBadge = childRepo !== undefined && groupBy !== 'repo'
const showChildBranch =
cardProps.includes('branch') && child.worktree.branch.trim() !== ''
const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
event.preventDefault()
event.stopPropagation()
@@ -2215,26 +2211,22 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
<div className="truncate text-[12px] leading-tight text-foreground">
{child.worktree.displayName}
</div>
{showChildRepoBadge || showChildBranch ? (
<div className="mt-1 flex min-w-0 items-center gap-1.5">
{showChildRepoBadge && childRepo ? (
<span className="flex h-[16px] shrink-0 items-center gap-1.5 rounded-[4px] border border-border bg-accent px-1.5 text-[10px] font-semibold leading-none text-foreground dark:bg-accent/50 dark:border-border/60">
<span
className="size-1.5 rounded-full"
style={{ backgroundColor: childRepo.badgeColor }}
/>
<span className="max-w-[6rem] truncate lowercase">
{childRepo.displayName}
</span>
<div className="mt-1 flex min-w-0 items-center gap-1.5">
{child.repo && groupBy !== 'repo' ? (
<span className="flex h-[16px] shrink-0 items-center gap-1.5 rounded-[4px] border border-border bg-accent px-1.5 text-[10px] font-semibold leading-none text-foreground dark:bg-accent/50 dark:border-border/60">
<span
className="size-1.5 rounded-full"
style={{ backgroundColor: child.repo.badgeColor }}
/>
<span className="max-w-[6rem] truncate lowercase">
{child.repo.displayName}
</span>
) : null}
{showChildBranch ? (
<span className="truncate text-[10.5px] leading-none text-muted-foreground">
{branchDisplayName(child.worktree.branch)}
</span>
) : null}
</div>
) : null}
</span>
) : null}
<span className="truncate text-[10.5px] leading-none text-muted-foreground">
{branchDisplayName(child.worktree.branch)}
</span>
</div>
{child.worktree.linkedIssue || child.worktree.comment ? (
<div className="mt-1.5 truncate text-[10.5px] leading-tight text-muted-foreground">
{child.worktree.linkedIssue ? (
-13
View File
@@ -547,19 +547,6 @@ describe('createUISlice hydratePersistedUI', () => {
expect(store.getState().worktreeCardProperties).toEqual(expected)
expect(setUI).toHaveBeenCalledWith({ worktreeCardProperties: expected })
})
it('persists Branch name as an opt-in card property', () => {
const setUI = vi.fn().mockResolvedValue(undefined)
vi.stubGlobal('window', { api: { ui: { set: setUI } } })
const store = createUIStore()
store.getState().toggleWorktreeCardProperty('branch')
expect(store.getState().worktreeCardProperties).toContain('branch')
expect(setUI).toHaveBeenCalledWith({
worktreeCardProperties: expect.arrayContaining(['status', 'unread', 'branch'])
})
})
})
describe('createUISlice settings navigation', () => {
+1 -11
View File
@@ -1,9 +1,5 @@
import { describe, expect, it } from 'vitest'
import {
getDefaultPrimarySelectionMiddleClickPaste,
getDefaultSettings,
getDefaultUIState
} from './constants'
import { getDefaultPrimarySelectionMiddleClickPaste, getDefaultSettings } from './constants'
describe('getDefaultSettings', () => {
it('enables gitignored file decorations by default', () => {
@@ -40,9 +36,3 @@ describe('getDefaultPrimarySelectionMiddleClickPaste', () => {
expect(getDefaultPrimarySelectionMiddleClickPaste('win32')).toBe(false)
})
})
describe('getDefaultUIState', () => {
it('keeps branch names hidden from workspace cards by default', () => {
expect(getDefaultUIState().worktreeCardProperties).not.toContain('branch')
})
})
-3
View File
@@ -2025,9 +2025,6 @@ export type NotificationPermissionStatusResult = {
export type WorktreeCardProperty =
| 'status'
| 'unread'
// Git branch metadata shown on workspace cards. Hidden by default because
// workspace names already carry the primary identity for most lists.
| 'branch'
// Legacy persisted preference. CI status is now represented by linked PR metadata.
| 'ci'
// GitHub issue metadata shown on workspace cards.
-1
View File
@@ -18,7 +18,6 @@ export const DEFAULT_WORKTREE_CARD_PROPERTIES: WorktreeCardProperty[] = [
const WORKTREE_CARD_PROPERTY_ORDER: WorktreeCardProperty[] = [
'status',
'unread',
'branch',
'ci',
'issue',
'linear-issue',