Keep inactive worktrees visible in dashboard

This commit is contained in:
brennanb2025 2026-04-14 16:16:27 -07:00
parent a2ace3ddfa
commit 673191cdd3
3 changed files with 32 additions and 10 deletions

View file

@ -95,11 +95,17 @@ function ListView({
<ChevronRight className="size-3" />
</div>
</div>
<div className="flex flex-col gap-1.5">
{rows.map((row) => (
<AgentRow key={row.key} row={row} now={now} />
))}
</div>
{rows.length > 0 ? (
<div className="flex flex-col gap-1.5">
{rows.map((row) => (
<AgentRow key={row.key} row={row} now={now} />
))}
</div>
) : (
<div className="rounded-md border border-dashed border-border/45 bg-muted/25 px-2 py-2 text-[10px] text-muted-foreground">
No active agents in this worktree
</div>
)}
</button>
))}
</div>
@ -128,10 +134,9 @@ export default function AgentDashboard(): React.JSX.Element {
return (
<div className="flex h-full items-center justify-center px-6 text-center">
<div className="max-w-[18rem] space-y-2">
<div className="text-sm font-medium text-foreground">No agent activity yet</div>
<div className="text-sm font-medium text-foreground">No worktrees yet</div>
<div className="text-xs leading-relaxed text-muted-foreground">
Claude and Codex sessions will appear here once a terminal pane reports hook-driven
lifecycle events or a live agent title is detected.
Add or create a worktree to populate the dashboard.
</div>
</div>
</div>

View file

@ -33,6 +33,14 @@ function AgentDots({
rows: RepoGroup['worktrees'][number]['rows']
now: number
}): React.JSX.Element {
if (rows.length === 0) {
return (
<div className="mt-2 text-[9px] uppercase tracking-[0.14em] text-muted-foreground/65">
No agents
</div>
)
}
return (
<div className="mt-2 flex flex-wrap justify-center gap-1">
{rows.slice(0, 6).map((row) => {
@ -119,7 +127,9 @@ function RepoOrb({
'hover:scale-[1.03] hover:border-foreground/30',
isActive
? 'border-foreground/35 bg-accent/70 shadow-[0_10px_30px_rgba(0,0,0,0.12)]'
: 'border-border/60 bg-background/90 shadow-[0_6px_20px_rgba(0,0,0,0.08)]'
: rows.length === 0
? 'border-border/45 bg-muted/35 shadow-[0_4px_16px_rgba(0,0,0,0.06)]'
: 'border-border/60 bg-background/90 shadow-[0_6px_20px_rgba(0,0,0,0.08)]'
)}
style={{
width: size,

View file

@ -103,7 +103,11 @@ export function buildRepoGroups(
.filter(isAgentRow)
.sort(compareRows)
return rows.length > 0 ? { worktree, rows } : null
// Why: the dashboard is also a global navigation surface. Keeping
// worktrees visible even with zero detected agents avoids a blank
// screen between lifecycle events and lets users jump straight to a
// dormant worktree from either the concentric or list view.
return { worktree, rows }
})
.filter((value): value is WorktreeGroup => value !== null) ?? []
@ -113,6 +117,9 @@ export function buildRepoGroups(
}
export function formatWorktreeStateSummary(rows: DashboardRow[], now: number): string {
if (rows.length === 0) {
return 'no agents'
}
const waiting = rows.filter((row) => getRowState(row, now).label === 'Waiting').length
const working = rows.filter((row) => getRowState(row, now).label === 'Working').length
if (waiting > 0) {