From 37519c2ee4b6b3017260f3725f6b19b7440b3bba Mon Sep 17 00:00:00 2001 From: huxcrux Date: Fri, 19 Jun 2026 03:49:58 +0200 Subject: [PATCH 1/4] Add middle-click close for right panel tabs --- .../src/components/RightPanelTabs.logic.test.ts | 11 +++++++++++ apps/web/src/components/RightPanelTabs.logic.ts | 3 +++ apps/web/src/components/RightPanelTabs.tsx | 16 ++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 apps/web/src/components/RightPanelTabs.logic.test.ts create mode 100644 apps/web/src/components/RightPanelTabs.logic.ts diff --git a/apps/web/src/components/RightPanelTabs.logic.test.ts b/apps/web/src/components/RightPanelTabs.logic.test.ts new file mode 100644 index 000000000000..177fcc20e39f --- /dev/null +++ b/apps/web/src/components/RightPanelTabs.logic.test.ts @@ -0,0 +1,11 @@ +import { describe, expect, it } from "vite-plus/test"; + +import { shouldCloseRightPanelTabOnAuxClick } from "./RightPanelTabs.logic"; + +describe("shouldCloseRightPanelTabOnAuxClick", () => { + it("closes right panel tabs only for middle mouse clicks", () => { + expect(shouldCloseRightPanelTabOnAuxClick(0)).toBe(false); + expect(shouldCloseRightPanelTabOnAuxClick(1)).toBe(true); + expect(shouldCloseRightPanelTabOnAuxClick(2)).toBe(false); + }); +}); diff --git a/apps/web/src/components/RightPanelTabs.logic.ts b/apps/web/src/components/RightPanelTabs.logic.ts new file mode 100644 index 000000000000..296d5ffee53b --- /dev/null +++ b/apps/web/src/components/RightPanelTabs.logic.ts @@ -0,0 +1,3 @@ +export function shouldCloseRightPanelTabOnAuxClick(button: number): boolean { + return button === 1; +} diff --git a/apps/web/src/components/RightPanelTabs.tsx b/apps/web/src/components/RightPanelTabs.tsx index ead306f7c906..88d5b00a0e30 100644 --- a/apps/web/src/components/RightPanelTabs.tsx +++ b/apps/web/src/components/RightPanelTabs.tsx @@ -23,6 +23,7 @@ import { useTheme } from "~/hooks/useTheme"; import { PreviewPanelShell, type PreviewPanelMode } from "./preview/PreviewPanelShell"; import { PierreEntryIcon } from "./chat/PierreEntryIcon"; +import { shouldCloseRightPanelTabOnAuxClick } from "./RightPanelTabs.logic"; interface RightPanelTabsProps { mode: PreviewPanelMode; @@ -330,6 +331,19 @@ export function RightPanelTabs(props: RightPanelTabsProps) { }, [props], ); + const handleTabMouseDown = useCallback((event: ReactMouseEvent) => { + if (!shouldCloseRightPanelTabOnAuxClick(event.button)) return; + event.preventDefault(); + }, []); + const handleTabAuxClick = useCallback( + (event: ReactMouseEvent, surface: RightPanelSurface) => { + if (!shouldCloseRightPanelTabOnAuxClick(event.button)) return; + event.preventDefault(); + event.stopPropagation(); + props.onCloseSurface(surface); + }, + [props], + ); useEffect(() => { const activeTab = tabListRef.current?.querySelector("[data-active-tab='true']"); @@ -365,6 +379,8 @@ export function RightPanelTabs(props: RightPanelTabsProps) {
handleTabAuxClick(event, surface)} onContextMenu={(event) => void handleTabContextMenu(event, surface)} className={cn( "group flex h-7 min-w-25 max-w-44 shrink-0 items-center gap-1.5 rounded-md px-2 text-sm", From 2425a0daba489c6872ff4e52080429444de3d0bc Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Tue, 30 Jun 2026 10:08:56 -0700 Subject: [PATCH 2/4] Delete apps/web/src/components/RightPanelTabs.logic.test.ts --- apps/web/src/components/RightPanelTabs.logic.test.ts | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 apps/web/src/components/RightPanelTabs.logic.test.ts diff --git a/apps/web/src/components/RightPanelTabs.logic.test.ts b/apps/web/src/components/RightPanelTabs.logic.test.ts deleted file mode 100644 index 177fcc20e39f..000000000000 --- a/apps/web/src/components/RightPanelTabs.logic.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { describe, expect, it } from "vite-plus/test"; - -import { shouldCloseRightPanelTabOnAuxClick } from "./RightPanelTabs.logic"; - -describe("shouldCloseRightPanelTabOnAuxClick", () => { - it("closes right panel tabs only for middle mouse clicks", () => { - expect(shouldCloseRightPanelTabOnAuxClick(0)).toBe(false); - expect(shouldCloseRightPanelTabOnAuxClick(1)).toBe(true); - expect(shouldCloseRightPanelTabOnAuxClick(2)).toBe(false); - }); -}); From 4df5d7ee905ac58bcd84ee4c6b8ffcd0a12c5f89 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Tue, 30 Jun 2026 10:09:25 -0700 Subject: [PATCH 3/4] Delete apps/web/src/components/RightPanelTabs.logic.ts --- apps/web/src/components/RightPanelTabs.logic.ts | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 apps/web/src/components/RightPanelTabs.logic.ts diff --git a/apps/web/src/components/RightPanelTabs.logic.ts b/apps/web/src/components/RightPanelTabs.logic.ts deleted file mode 100644 index 296d5ffee53b..000000000000 --- a/apps/web/src/components/RightPanelTabs.logic.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function shouldCloseRightPanelTabOnAuxClick(button: number): boolean { - return button === 1; -} From 811baa19d32b5aef026d532a9b38ea0b054452e7 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Tue, 30 Jun 2026 10:10:20 -0700 Subject: [PATCH 4/4] Refactor tab click handling to use button check --- apps/web/src/components/RightPanelTabs.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/web/src/components/RightPanelTabs.tsx b/apps/web/src/components/RightPanelTabs.tsx index d9b998f9436f..f5bc9880d74f 100644 --- a/apps/web/src/components/RightPanelTabs.tsx +++ b/apps/web/src/components/RightPanelTabs.tsx @@ -24,7 +24,6 @@ import { COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS } from "~/workspaceTitlebar"; import { PreviewPanelShell, type PreviewPanelMode } from "./preview/PreviewPanelShell"; import { PierreEntryIcon } from "./chat/PierreEntryIcon"; -import { shouldCloseRightPanelTabOnAuxClick } from "./RightPanelTabs.logic"; interface RightPanelTabsProps { mode: PreviewPanelMode; @@ -333,12 +332,12 @@ export function RightPanelTabs(props: RightPanelTabsProps) { [props], ); const handleTabMouseDown = useCallback((event: ReactMouseEvent) => { - if (!shouldCloseRightPanelTabOnAuxClick(event.button)) return; + if (event.button !== 1) return; event.preventDefault(); }, []); const handleTabAuxClick = useCallback( (event: ReactMouseEvent, surface: RightPanelSurface) => { - if (!shouldCloseRightPanelTabOnAuxClick(event.button)) return; + if (event.button !== 1) return; event.preventDefault(); event.stopPropagation(); props.onCloseSurface(surface);