From f91220934ae19a0ba70070281e3f045f3903c520 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 12 Nov 2026 07:38:07 +0000 Subject: [PATCH 1/2] test(web): a sidebar press that never drags keeps its click Fails on main: a zero-button pointermove before pointerup cancels a pending press and installs click suppression, so the row's click is lost. Refs pingdotgg/t3code#22058 AI-assisted; verified with the tests and tools listed above. --- .../components/Sidebar.pointer.browser.test.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/apps/web/src/components/Sidebar.pointer.browser.test.tsx b/apps/web/src/components/Sidebar.pointer.browser.test.tsx index 2cbaab9e14e5..fee907f6aeff 100644 --- a/apps/web/src/components/Sidebar.pointer.browser.test.tsx +++ b/apps/web/src/components/Sidebar.pointer.browser.test.tsx @@ -71,6 +71,22 @@ describe("sidebar pointer lifecycle", () => { expect(drag.onFinish).toHaveBeenCalledExactlyOnceWith(true); }); + // regression: #22058 a press that never became a drag must keep its click + it("keeps the click when a zero-button move precedes pointerup before activation", () => { + using _environment = setup(); + const press = gesture(); + document.dispatchEvent(pointer("pointermove", { clientX: 11 })); + document.dispatchEvent(pointer("pointermove", { buttons: 0, clientX: 12 })); + document.dispatchEvent(pointer("pointerup", { buttons: 0, clientX: 12 })); + const onClick = vi.fn(); + document.body.addEventListener("click", onClick); + document.body.dispatchEvent(new MouseEvent("click", { bubbles: true })); + document.body.removeEventListener("click", onClick); + + expect(press.onCancel).not.toHaveBeenCalled(); + expect(onClick).toHaveBeenCalledOnce(); + }); + // regression: #17373 a zero-button release outside a drop target must cancel, not reorder it("cancels a missed sidebar release without committing a reorder", () => { using _environment = setup(); From 10d5186195f48b0119454afd5c55ed28a16d03a0 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Thu, 12 Nov 2026 07:43:50 +0000 Subject: [PATCH 2/2] fix(web): a sidebar click no longer gets lost when the release reports no buttons A buttons=0 pointermove before pointerup cancelled a press that had not yet passed the drag distance and installed click suppression, so the row's click never ran and thread switching took several clicks. A pending press now finishes like a normal release; active drags still drop context and cancel. Fixes pingdotgg/t3code#22058 AI-assisted; verified with the tests and tools listed above. --- apps/web/src/components/Sidebar.pointer.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/web/src/components/Sidebar.pointer.ts b/apps/web/src/components/Sidebar.pointer.ts index 5a0ce373c077..7aa1bf352b03 100644 --- a/apps/web/src/components/Sidebar.pointer.ts +++ b/apps/web/src/components/Sidebar.pointer.ts @@ -59,9 +59,11 @@ export class SidebarPointerSensor { private move = (event: PointerEvent) => { if (this.phase === "finished" || event.pointerId !== this.pointer.pointerId) return; const coordinates = { x: event.clientX, y: event.clientY }; - // Desktop may report buttons=0 before pointerup; drop active context drags before cancelling sort. + // Desktop may report buttons=0 before pointerup: a pending press is released like pointerup so its + // click lands; an active drag drops context before cancelling sort. if ((event.buttons & 1) === 0) { - if (this.phase === "dragging") this.props.options.onDrop?.(coordinates); + if (this.phase === "pending") return this.finish(false); + this.props.options.onDrop?.(coordinates); return this.cancel(); } if (this.phase === "pending") {