From c27c321a8b7d825c9441145302cc0de278234045 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Tue, 9 Jun 2026 22:13:54 -0700 Subject: [PATCH] FN-6160: fix mobile quick-entry touch handling Let mobile Quick Entry actions rely on native tap-to-click behavior again. - remove the manual quick-entry action button click dispatch on touchend - switch mobile quick-entry action buttons to touch-action: manipulation - update QuickEntryBox mobile touch tests and add a patch changeset for @runfusion/fusion Files changed: .changeset/tiny-mobile-clicks.md | 5 +++++ packages/dashboard/app/components/QuickEntryBox.css | 4 ++-- packages/dashboard/app/components/QuickEntryBox.tsx | 9 --------- packages/dashboard/app/components/__tests__/QuickEntryBox.test.tsx | 14 +++++++++++++- 4 files changed, 20 insertions(+), 12 deletions(-) Fusion-Task-Id: FN-6160 Fusion-Task-Lineage: a8c13f7e-fb86-4087-a516-a6e16dac2092 --- .changeset/tiny-mobile-clicks.md | 5 +++++ .../dashboard/app/components/QuickEntryBox.css | 4 ++-- .../dashboard/app/components/QuickEntryBox.tsx | 9 --------- .../components/__tests__/QuickEntryBox.test.tsx | 14 +++++++++++++- 4 files changed, 20 insertions(+), 12 deletions(-) create mode 100644 .changeset/tiny-mobile-clicks.md diff --git a/.changeset/tiny-mobile-clicks.md b/.changeset/tiny-mobile-clicks.md new file mode 100644 index 0000000000..a7cd80d601 --- /dev/null +++ b/.changeset/tiny-mobile-clicks.md @@ -0,0 +1,5 @@ +--- +"@runfusion/fusion": patch +--- + +Fix mobile Quick Entry action buttons so taps rely on native browser click synthesis instead of a manual touchend click. diff --git a/packages/dashboard/app/components/QuickEntryBox.css b/packages/dashboard/app/components/QuickEntryBox.css index 4491016bc1..bf947e022d 100644 --- a/packages/dashboard/app/components/QuickEntryBox.css +++ b/packages/dashboard/app/components/QuickEntryBox.css @@ -428,11 +428,11 @@ } } -/* === Quick Entry Mobile Touch + Overflow Fixes (FN-1140, FN-6153) === */ +/* === Quick Entry Mobile Touch + Overflow Fixes (FN-1140, FN-6153, FN-6160) === */ @media (max-width: 768px) { .quick-entry-actions, .quick-entry-actions * { - touch-action: none; + touch-action: manipulation; } .quick-entry-actions .btn { diff --git a/packages/dashboard/app/components/QuickEntryBox.tsx b/packages/dashboard/app/components/QuickEntryBox.tsx index 31cf93455a..4a639b7bca 100644 --- a/packages/dashboard/app/components/QuickEntryBox.tsx +++ b/packages/dashboard/app/components/QuickEntryBox.tsx @@ -1492,16 +1492,7 @@ export function QuickEntryBox({ onCreate, addToast, tasks = [], availableModels, } }} onTouchEnd={() => { - const button = touchButtonRef.current; touchButtonRef.current = null; - if (button && !button.disabled) { - button.click(); - window.setTimeout(() => { - window.setTimeout(() => { - textareaRef.current?.focus({ preventScroll: true }); - }, 0); - }, 0); - } }} onTouchCancel={() => { touchButtonRef.current = null; diff --git a/packages/dashboard/app/components/__tests__/QuickEntryBox.test.tsx b/packages/dashboard/app/components/__tests__/QuickEntryBox.test.tsx index f7c62bc87b..936e19a791 100644 --- a/packages/dashboard/app/components/__tests__/QuickEntryBox.test.tsx +++ b/packages/dashboard/app/components/__tests__/QuickEntryBox.test.tsx @@ -505,6 +505,7 @@ describe("QuickEntryBox", () => { expect(preventDefaultSpy).toHaveBeenCalled(); await act(async () => { fireEvent(button, new Event("touchend", { bubbles: true, cancelable: true })); + fireEvent.click(button); vi.runOnlyPendingTimers(); vi.runOnlyPendingTimers(); }); @@ -530,6 +531,7 @@ describe("QuickEntryBox", () => { expect(preventDefaultSpy).toHaveBeenCalled(); await act(async () => { fireEvent(svg!, new Event("touchend", { bubbles: true, cancelable: true })); + fireEvent.click(priorityButton); vi.runOnlyPendingTimers(); vi.runOnlyPendingTimers(); }); @@ -569,6 +571,7 @@ describe("QuickEntryBox", () => { expect(preventDefaultSpy).toHaveBeenCalled(); await act(async () => { fireEvent(svg!, new Event("touchend", { bubbles: true, cancelable: true })); + fireEvent.click(githubToggle); vi.runOnlyPendingTimers(); vi.runOnlyPendingTimers(); }); @@ -653,10 +656,19 @@ describe("QuickEntryBox", () => { expect(document.activeElement).toBe(textarea); await act(async () => { fireEvent(button, new Event("touchend", { bubbles: true, cancelable: true })); + fireEvent.click(button); vi.runOnlyPendingTimers(); vi.runOnlyPendingTimers(); }); expect(document.activeElement).toBe(textarea); + + const outsideElement = document.createElement("div"); + document.body.appendChild(outsideElement); + try { + fireEvent.mouseDown(outsideElement); + } finally { + document.body.removeChild(outsideElement); + } }); it("does not fire disabled button actions via touch", async () => { @@ -3218,7 +3230,7 @@ describe("QuickEntryBox", () => { const touchRule = quickEntryMobileActionsTouchRule(); expect(touchRule).toMatch(/\.quick-entry-actions,\s*\.quick-entry-actions \*/); - expect(touchRule).toMatch(/touch-action:\s*none;/); + expect(touchRule).toMatch(/touch-action:\s*manipulation;/); }); it("keeps inline deps/models controls in touch-target button classes on mobile", () => {