From 8849eb8144d61cf2bfa9102039041c43a2b512a9 Mon Sep 17 00:00:00 2001 From: Jake Leventhal Date: Tue, 6 Oct 2026 18:40:23 -0400 Subject: [PATCH 1/2] fix(web): open pull request row actions on right-click --- .../components/pullRequest/ThreadPullRequestsPanel.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx b/apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx index 643c17d4b775..f398c9d1c93c 100644 --- a/apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx +++ b/apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx @@ -11,7 +11,7 @@ import { MoreHorizontalIcon, PlusIcon, } from "lucide-react"; -import { useCallback, useMemo } from "react"; +import { useCallback, useMemo, useState } from "react"; import { writeTextToClipboard } from "~/hooks/useCopyToClipboard"; import { useOpenPrLink } from "~/lib/openPullRequestLink"; @@ -84,6 +84,7 @@ function LinkRow({ onSetWatching: ((link: ThreadPullRequestLink, watching: boolean) => void) | null; }) { const openPrLink = useOpenPrLink(threadRef); + const [menuOpen, setMenuOpen] = useState(false); const { link, depth, stack } = line; const snapshot = link.snapshot; const open = snapshot === null || snapshot.state === "open"; @@ -91,6 +92,11 @@ function LinkRow({ return (
{ + event.preventDefault(); + event.stopPropagation(); + setMenuOpen(true); + }} // Each layer steps in under the one it targets. The step is capped: beyond a few layers // the indent only says "still in the stack", which the connector line already does, and // a sixteen-layer stack would otherwise stair-step off the right edge. @@ -221,7 +227,7 @@ function LinkRow({ )} > - + Date: Tue, 6 Oct 2026 18:44:53 -0400 Subject: [PATCH 2/2] fix(web): position pull request context menu at the pointer --- .../pullRequest/ThreadPullRequestsPanel.tsx | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx b/apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx index f398c9d1c93c..42b09f4387e7 100644 --- a/apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx +++ b/apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx @@ -85,6 +85,14 @@ function LinkRow({ }) { const openPrLink = useOpenPrLink(threadRef); const [menuOpen, setMenuOpen] = useState(false); + const [menuPosition, setMenuPosition] = useState<{ x: number; y: number } | null>(null); + const menuAnchor = useMemo( + () => + menuPosition + ? { getBoundingClientRect: () => new DOMRect(menuPosition.x, menuPosition.y, 0, 0) } + : undefined, + [menuPosition], + ); const { link, depth, stack } = line; const snapshot = link.snapshot; const open = snapshot === null || snapshot.state === "open"; @@ -95,6 +103,7 @@ function LinkRow({ onContextMenu={(event) => { event.preventDefault(); event.stopPropagation(); + setMenuPosition({ x: event.clientX, y: event.clientY }); setMenuOpen(true); }} // Each layer steps in under the one it targets. The step is capped: beyond a few layers @@ -227,7 +236,13 @@ function LinkRow({ )} > - + { + setMenuOpen(open); + if (!open) setMenuPosition(null); + }} + > } /> - + void writeTextToClipboard(link.url, "link")}> Copy link