From bb5f68c2f0abd3a0541348fbe1310159e2e17fc1 Mon Sep 17 00:00:00 2001 From: Cody Seibert Date: Fri, 19 Dec 2025 20:46:23 -0500 Subject: [PATCH] refactor: improve PR display and interaction in worktree components - Updated WorktreeActionsDropdown to use DropdownMenuItem for better interaction with PR links. - Enhanced WorktreeTab to include hover and active states for buttons, and improved accessibility with updated titles and aria-labels. - Ensured PR URLs are safely opened only if they exist, enhancing user experience and preventing errors. --- .../components/worktree-actions-dropdown.tsx | 13 +++++++++---- .../worktree-panel/components/worktree-tab.tsx | 16 ++++++++++------ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-actions-dropdown.tsx b/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-actions-dropdown.tsx index 45cf15e7..397f2c1b 100644 --- a/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-actions-dropdown.tsx +++ b/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-actions-dropdown.tsx @@ -185,13 +185,18 @@ export function WorktreeActionsDropdown({ {/* Show PR info and Address Comments button if PR exists */} {!worktree.isMain && hasPR && worktree.pr && ( <> - - + { + window.open(worktree.pr!.url, "_blank"); + }} + className="text-xs" + > + PR #{worktree.pr.number} - + {worktree.pr.state} - + { // Convert stored PR info to the full PRInfo format for the handler diff --git a/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx b/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx index b3134191..dfb27104 100644 --- a/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx +++ b/apps/ui/src/components/views/board-view/worktree-panel/components/worktree-tab.tsx @@ -157,7 +157,7 @@ export function WorktreeTab({ className={cn( "ml-1.5 inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-[10px] font-medium transition-colors", "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 focus:ring-offset-background", - "appearance-none cursor-pointer", // Reset button appearance but keep cursor + "appearance-none cursor-pointer hover:opacity-80 active:opacity-70", // Reset button appearance but keep cursor, add hover/active states prStateClasses )} style={{ @@ -165,24 +165,28 @@ export function WorktreeTab({ backgroundImage: "none", boxShadow: "none", }} - title={prLabel} - aria-label={prLabel} + title={`${prLabel} - Click to open`} + aria-label={`${prLabel} - Click to open pull request`} onClick={(e) => { e.stopPropagation(); // Prevent triggering worktree selection - window.open(worktree.pr.url, "_blank", "noopener,noreferrer"); + if (worktree.pr?.url) { + window.open(worktree.pr.url, "_blank", "noopener,noreferrer"); + } }} onKeyDown={(e) => { // Prevent event from bubbling to parent button e.stopPropagation(); if (e.key === "Enter" || e.key === " ") { e.preventDefault(); - window.open(worktree.pr.url, "_blank", "noopener,noreferrer"); + if (worktree.pr?.url) { + window.open(worktree.pr.url, "_blank", "noopener,noreferrer"); + } } }} >