From 85c0f63e29ce4f9fef0e5bd87e19b460aeb4e008 Mon Sep 17 00:00:00 2001 From: Caroline di Vittorio <43390382+carolinedivittorio@users.noreply.github.com> Date: Fri, 26 Jun 2026 12:54:51 -0700 Subject: [PATCH] feat: clickable shared PR header in git panel and reviews (#1620) * feat: clickable shared PR header in git panel and reviews Replace the standalone "View PR" button in the agent git panel with a clickable PR title, matching the reviews view. Extract a shared PrHeader component reused by both the git panel and the review main body. Co-authored-by: open-swe[bot] * refactor: drop PrHeader wrapper, use shared component directly The review-side PrHeader was just a thin adapter mapping detail -> the shared component's props. Inline it at the call site and use the shared PrHeader directly so there's a single component. Co-authored-by: open-swe[bot] --------- Co-authored-by: open-swe[bot] --- ui/src/components/agents/AgentGitPanel.tsx | 45 +++-------- ui/src/components/agents/PrHeader.tsx | 88 +++++++++++++++++++++ ui/src/components/agents/ReviewMainBody.tsx | 66 ++++------------ 3 files changed, 113 insertions(+), 86 deletions(-) create mode 100644 ui/src/components/agents/PrHeader.tsx diff --git a/ui/src/components/agents/AgentGitPanel.tsx b/ui/src/components/agents/AgentGitPanel.tsx index ce8a1841..daa3c784 100644 --- a/ui/src/components/agents/AgentGitPanel.tsx +++ b/ui/src/components/agents/AgentGitPanel.tsx @@ -10,11 +10,9 @@ import { useFileTreeSelection, } from "@pierre/trees/react" import { - ArrowSquareOutIcon, ArrowsInIcon, ArrowsOutIcon, CaretDownIcon, - GitPullRequestIcon, SidebarSimpleIcon, } from "@phosphor-icons/react" import type { FileContents } from "@pierre/diffs/react" @@ -26,6 +24,7 @@ import type { ChangedFileSummaryItem } from "@/components/agents/messages" import { agentsApi } from "@/lib/agents/api" import { useAgentThreadPrDiff } from "@/lib/agents/queries" import { ReviewTab } from "@/components/agents/ReviewTab" +import { PrHeader } from "@/components/agents/PrHeader" import { buttonVariants } from "@/components/ui/button" import { DIFF_VIRTUALIZER_CONFIG, @@ -518,38 +517,16 @@ export function AgentGitPanel({ ) : ( <> {pr && ( -
-
-
-
- {pr.title} #{pr.number} -
-
- - - {pr.state} - - - {pr.headRef} → {pr.baseRef} - -
-
- {pr.url && ( - - - View PR - - )} -
-
+ )}
diff --git a/ui/src/components/agents/PrHeader.tsx b/ui/src/components/agents/PrHeader.tsx new file mode 100644 index 00000000..347231c0 --- /dev/null +++ b/ui/src/components/agents/PrHeader.tsx @@ -0,0 +1,88 @@ +import { GitPullRequestIcon } from "@phosphor-icons/react" + +import { cn } from "@/lib/utils" + +const STATE_STYLES: Record = { + open: "border-emerald-600/40 text-emerald-500", + draft: "border-border text-muted-foreground", + merged: "border-purple-600/40 text-purple-500", + closed: "border-red-600/40 text-red-500", +} + +export interface PrHeaderProps { + url: string + title: string + state: string + headRef: string + baseRef: string + number?: number | null + author?: string | null + stats?: { + changedFiles: number + additions: number + deletions: number + } | null + className?: string + titleClassName?: string +} + +export function PrHeader({ + url, + title, + state, + headRef, + baseRef, + number, + author, + stats, + className, + titleClassName, +}: PrHeaderProps) { + return ( +
+ + + {state} + +

+ + {title} + {number != null && ( + #{number} + )} + +

+
+ {author && ( + {author} + )} + + {baseRef} + + ← + + {headRef} + + {stats && ( + <> + + {stats.changedFiles} file{stats.changedFiles === 1 ? "" : "s"} + + +{stats.additions} + -{stats.deletions} + + )} +
+
+ ) +} diff --git a/ui/src/components/agents/ReviewMainBody.tsx b/ui/src/components/agents/ReviewMainBody.tsx index 9fa30a78..a58fe86a 100644 --- a/ui/src/components/agents/ReviewMainBody.tsx +++ b/ui/src/components/agents/ReviewMainBody.tsx @@ -22,7 +22,6 @@ import { CodeIcon, CopyIcon, FlagIcon, - GitPullRequestIcon, InfoIcon, LinkIcon, ListBulletsIcon, @@ -68,6 +67,7 @@ import type { import type { ChatAttachment } from "@/components/agents/ReviewChat" import type { DiffStyle } from "@/components/agents/utils/diffUtils" import { Markdown } from "@/components/agents/ported" +import { PrHeader } from "@/components/agents/PrHeader" import { ReviewChat, ReviewChatComposerProvider, @@ -1120,7 +1120,19 @@ function ReviewBodyInner({ config={DIFF_VIRTUALIZER_CONFIG} >
- +
{detail.pr.body ? ( = { - open: "border-emerald-600/40 text-emerald-500", - draft: "border-border text-muted-foreground", - merged: "border-purple-600/40 text-purple-500", - closed: "border-red-600/40 text-red-500", - } - return ( -
- - - {pr.state} - -

- - {pr.title} - -

-
- {pr.author && ( - {pr.author.login} - )} - - {pr.base_ref} - - ← - - {pr.head_ref} - - - {pr.changed_files} file{pr.changed_files === 1 ? "" : "s"} - - +{pr.additions} - -{pr.deletions} -
-
- ) -} - function GroupHeader({ group }: { group: ResolvedGroup }) { return (