feat(agent-manager): show checkmark on approved PR badges (#8657)

* feat(agent-manager): show checkmark on approved PR badges

Replace the branch icon with a check-small icon when
pr.review === "approved", making merge-ready PRs visually
distinct at a glance. Add 10 Storybook stories covering every
PR badge color/state combination for visual regression.

* chore: update kilo-vscode visual regression baselines

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Marius
2026-04-09 12:54:21 +02:00
committed by GitHub
co-authored by github-actions[bot]
parent d65ee14cfb
commit b64d2babe4
12 changed files with 176 additions and 2 deletions
@@ -50,6 +50,7 @@ async function disableAnimations(page: Page) {
// Permission dock config-preloaded has non-deterministic toggle rendering.
const SKIP = new Set<string>([
"agentmanager--worktree-item-busy",
"agentmanager--pr-badge-checks-pending",
"composite-webview--permission-dock-config-preloaded",
])
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:facae793453671cf34b950352dc19041d420d096fac2a7358d1a4550e05a8033
size 3383
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fc81d91792781a9784775db3af44ea8058e87df9e029c2d7fc5acf1548fa7ec7
size 3423
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2923838fbc9ce24851e2b8ed6c5d4c2a098db9667fc528d1c00162595640bc05
size 3550
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c087f8e2b50bf43f9ca03ab31e8955e995304473688bf8db88fb6901d743a1d4
size 3541
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6c13cc44cec6092d8294a535a3e6057d6e3a2b2d59cb18e09b0a073576972f80
size 3582
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:79f5495b171fc9de3d04b7e15cc30ac2f5082c6d7db3818b3e288ce9c3ba41f3
size 3461
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dda50cfb4ebebd29e6f0791ec13ee9e16e48c9fa6f6d6be03c78b1d900516427
size 3604
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2680e8f97baee13ab92ac6fb3bcce56eb9cbb7e0c5fb0f76a76251abc016eac3
size 3567
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2680e8f97baee13ab92ac6fb3bcce56eb9cbb7e0c5fb0f76a76251abc016eac3
size 3567
@@ -297,7 +297,7 @@ export const WorktreeItem: Component<WorktreeItemProps> = (props) => {
data-pending={pr().state === "open" && pr().checks.status === "pending" ? "" : undefined}
onClick={handleOpenPR}
>
<Icon name="branch" size="small" />
<Icon name={pr().review === "approved" ? "check-small" : "branch"} size="small" />
<span class="am-pr-badge-number">#{pr().number}</span>
</span>
)
@@ -10,7 +10,7 @@ import { FileTree } from "../../agent-manager/FileTree"
import { DiffPanel } from "../../agent-manager/DiffPanel"
import { FullScreenDiffView } from "../../agent-manager/FullScreenDiffView"
import { WorktreeItem } from "../../agent-manager/WorktreeItem"
import type { WorktreeFileDiff, WorktreeState, WorktreeGitStats } from "../types/messages"
import type { WorktreeFileDiff, WorktreeState, WorktreeGitStats, PRStatus } from "../types/messages"
import "../../agent-manager/agent-manager.css"
import "../../agent-manager/agent-manager-review.css"
@@ -252,6 +252,152 @@ export const WorktreeItemWithStats: Story = {
),
}
// ---------------------------------------------------------------------------
// PR badge mock helpers
// ---------------------------------------------------------------------------
const basePR: PRStatus = {
number: 8594,
title: "feat: add inline delete",
url: "https://github.com/org/repo/pull/8594",
state: "open",
review: null,
checks: { status: "success", total: 5, passed: 5, failed: 0, pending: 0, items: [] },
additions: 978,
deletions: 202,
files: 12,
}
// ---------------------------------------------------------------------------
// WorktreeItem — PR badge stories
// ---------------------------------------------------------------------------
export const PRBadgeApproved: Story = {
name: "PR Badge — approved + checks pass",
render: () => (
<StoryProviders noPadding>
<div style={{ width: "200px" }}>
<WorktreeItem {...defaultProps} stats={baseStats} pr={{ ...basePR, review: "approved" }} />
</div>
</StoryProviders>
),
}
export const PRBadgePending: Story = {
name: "PR Badge — pending review",
render: () => (
<StoryProviders noPadding>
<div style={{ width: "200px" }}>
<WorktreeItem {...defaultProps} stats={baseStats} pr={{ ...basePR, review: "pending" }} />
</div>
</StoryProviders>
),
}
export const PRBadgeChangesRequested: Story = {
name: "PR Badge — changes requested",
render: () => (
<StoryProviders noPadding>
<div style={{ width: "200px" }}>
<WorktreeItem {...defaultProps} stats={baseStats} pr={{ ...basePR, review: "changes_requested" }} />
</div>
</StoryProviders>
),
}
export const PRBadgeChecksFailing: Story = {
name: "PR Badge — checks failing",
render: () => (
<StoryProviders noPadding>
<div style={{ width: "200px" }}>
<WorktreeItem
{...defaultProps}
stats={baseStats}
pr={{ ...basePR, checks: { ...basePR.checks, status: "failure", passed: 3, failed: 2 } }}
/>
</div>
</StoryProviders>
),
}
export const PRBadgeChecksPending: Story = {
name: "PR Badge — checks pending",
render: () => (
<StoryProviders noPadding>
<div style={{ width: "200px" }}>
<WorktreeItem
{...defaultProps}
stats={baseStats}
pr={{ ...basePR, checks: { ...basePR.checks, status: "pending", passed: 2, pending: 3 } }}
/>
</div>
</StoryProviders>
),
}
export const PRBadgeDraft: Story = {
name: "PR Badge — draft",
render: () => (
<StoryProviders noPadding>
<div style={{ width: "200px" }}>
<WorktreeItem {...defaultProps} stats={baseStats} pr={{ ...basePR, state: "draft" }} />
</div>
</StoryProviders>
),
}
export const PRBadgeMerged: Story = {
name: "PR Badge — merged",
render: () => (
<StoryProviders noPadding>
<div style={{ width: "200px" }}>
<WorktreeItem {...defaultProps} stats={baseStats} pr={{ ...basePR, state: "merged" }} />
</div>
</StoryProviders>
),
}
export const PRBadgeClosed: Story = {
name: "PR Badge — closed",
render: () => (
<StoryProviders noPadding>
<div style={{ width: "200px" }}>
<WorktreeItem {...defaultProps} stats={baseStats} pr={{ ...basePR, state: "closed" }} />
</div>
</StoryProviders>
),
}
export const PRBadgeNoReview: Story = {
name: "PR Badge — open, no review decision",
render: () => (
<StoryProviders noPadding>
<div style={{ width: "200px" }}>
<WorktreeItem {...defaultProps} stats={baseStats} pr={basePR} />
</div>
</StoryProviders>
),
}
export const PRBadgeApprovedChecksFailing: Story = {
name: "PR Badge — approved but checks failing",
render: () => (
<StoryProviders noPadding>
<div style={{ width: "200px" }}>
<WorktreeItem
{...defaultProps}
stats={baseStats}
pr={{ ...basePR, review: "approved", checks: { ...basePR.checks, status: "failure", passed: 3, failed: 2 } }}
/>
</div>
</StoryProviders>
),
}
// ---------------------------------------------------------------------------
// WorktreeItem — grouped
// ---------------------------------------------------------------------------
export const WorktreeItemGrouped: Story = {
name: "WorktreeItem — grouped (3 versions)",
render: () => {