Skip to content

Commit d8d037e

Browse files
fix(web): open pull request row actions on right-click (#16612)
1 parent 13aabf3 commit d8d037e

1 file changed

Lines changed: 29 additions & 3 deletions

File tree

‎apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx‎

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
MoreHorizontalIcon,
1212
PlusIcon,
1313
} from "lucide-react";
14-
import { useCallback, useMemo } from "react";
14+
import { useCallback, useMemo, useState } from "react";
1515

1616
import { writeTextToClipboard } from "~/hooks/useCopyToClipboard";
1717
import { useOpenPrLink } from "~/lib/openPullRequestLink";
@@ -84,13 +84,28 @@ function LinkRow({
8484
onSetWatching: ((link: ThreadPullRequestLink, watching: boolean) => void) | null;
8585
}) {
8686
const openPrLink = useOpenPrLink(threadRef);
87+
const [menuOpen, setMenuOpen] = useState(false);
88+
const [menuPosition, setMenuPosition] = useState<{ x: number; y: number } | null>(null);
89+
const menuAnchor = useMemo(
90+
() =>
91+
menuPosition
92+
? { getBoundingClientRect: () => new DOMRect(menuPosition.x, menuPosition.y, 0, 0) }
93+
: undefined,
94+
[menuPosition],
95+
);
8796
const { link, depth, stack } = line;
8897
const snapshot = link.snapshot;
8998
const open = snapshot === null || snapshot.state === "open";
9099
const watching = link.watch !== undefined;
91100
return (
92101
<div
93102
className={cn(PULL_REQUEST_ROW_CLASS, "relative hover:bg-accent/60")}
103+
onContextMenu={(event) => {
104+
event.preventDefault();
105+
event.stopPropagation();
106+
setMenuPosition({ x: event.clientX, y: event.clientY });
107+
setMenuOpen(true);
108+
}}
94109
// Each layer steps in under the one it targets. The step is capped: beyond a few layers
95110
// the indent only says "still in the stack", which the connector line already does, and
96111
// a sixteen-layer stack would otherwise stair-step off the right edge.
@@ -221,7 +236,13 @@ function LinkRow({
221236
)}
222237
>
223238
<span aria-hidden className="absolute inset-0 bg-accent/60" />
224-
<Menu>
239+
<Menu
240+
open={menuOpen}
241+
onOpenChange={(open) => {
242+
setMenuOpen(open);
243+
if (!open) setMenuPosition(null);
244+
}}
245+
>
225246
<MenuTrigger
226247
render={
227248
<Button
@@ -234,7 +255,12 @@ function LinkRow({
234255
</Button>
235256
}
236257
/>
237-
<MenuPopup align="end" side="bottom">
258+
<MenuPopup
259+
anchor={menuAnchor}
260+
align={menuPosition ? "start" : "end"}
261+
side="bottom"
262+
sideOffset={menuPosition ? 0 : 4}
263+
>
238264
<MenuItem onClick={() => void writeTextToClipboard(link.url, "link")}>
239265
<LinkIcon className="size-3.5" />
240266
Copy link

0 commit comments

Comments
 (0)