diff --git a/apps/web/src/components/RightPanelTabs.test.tsx b/apps/web/src/components/RightPanelTabs.test.tsx new file mode 100644 index 00000000000..0777f7b5595 --- /dev/null +++ b/apps/web/src/components/RightPanelTabs.test.tsx @@ -0,0 +1,52 @@ +import { renderToStaticMarkup } from "react-dom/server"; +import { describe, expect, it, vi } from "vite-plus/test"; + +import { RightPanelTabs } from "./RightPanelTabs"; + +vi.mock("~/env", () => ({ isElectron: true })); + +/** The opening tag carrying `attribute`, so class assertions pin the element, not attribute order. */ +function tagWith(markup: string, attribute: string): string { + const index = markup.indexOf(attribute); + if (index === -1) throw new Error(`no element carries ${attribute}`); + return markup.slice(markup.lastIndexOf("<", index), markup.indexOf(">", index) + 1); +} + +describe("RightPanelTabs", () => { + it("keeps the Electron titlebar draggable without swallowing tab strip scrolling", () => { + const markup = renderToStaticMarkup( + +
+ , + ); + + expect(tagWith(markup, "data-right-panel-tabbar")).toContain("drag-region"); + + // -webkit-app-region: drag swallows pointer and wheel events, so the scroll + // container itself must opt out or the tab strip cannot be scrolled. + const tabList = tagWith(markup, "data-right-panel-tab-list"); + expect(tabList).toContain("[-webkit-app-region:no-drag]"); + expect(tabList).not.toContain("drag-region"); + }); +}); diff --git a/apps/web/src/components/RightPanelTabs.tsx b/apps/web/src/components/RightPanelTabs.tsx index b0f18f6e126..611266c7126 100644 --- a/apps/web/src/components/RightPanelTabs.tsx +++ b/apps/web/src/components/RightPanelTabs.tsx @@ -374,7 +374,8 @@ export function RightPanelTabs(props: RightPanelTabsProps) { "workspace-topbar gap-1 pl-2", props.mode !== "inline" && "[--workspace-topbar-height:--spacing(11)]", props.mode === "inline" ? "pr-28" : "pr-3", - ownsDesktopTitleBar && "wco:pr-[calc(var(--workspace-native-controls-inset)+6rem)]", + ownsDesktopTitleBar && + "drag-region wco:pr-[calc(var(--workspace-native-controls-inset)+6rem)]", props.mode === "inline" && props.maximized && COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS, )} data-right-panel-tabbar @@ -383,7 +384,10 @@ export function RightPanelTabs(props: RightPanelTabsProps) { ref={tabListRef} hideScrollbars scrollFade - className={cn("min-w-0 flex-1 rounded-none", ownsDesktopTitleBar && "drag-region")} + className={cn( + "min-w-0 flex-1 rounded-none", + ownsDesktopTitleBar && "[-webkit-app-region:no-drag]", + )} data-right-panel-tab-list >