diff --git a/.changeset/fn-8474-tablet-task-popup-gutter.md b/.changeset/fn-8474-tablet-task-popup-gutter.md
new file mode 100644
index 0000000000..860b6ecc9d
--- /dev/null
+++ b/.changeset/fn-8474-tablet-task-popup-gutter.md
@@ -0,0 +1,7 @@
+---
+"@runfusion/fusion": patch
+---
+
+summary: Remove excess right padding from task popups on tablets.
+category: fix
+dev: Tablet task popups no longer reserve desktop resize-handle scrollbar clearance.
diff --git a/packages/dashboard/app/components/FloatingWindow.css b/packages/dashboard/app/components/FloatingWindow.css
index 6902dff866..a812a8012d 100644
--- a/packages/dashboard/app/components/FloatingWindow.css
+++ b/packages/dashboard/app/components/FloatingWindow.css
@@ -106,6 +106,20 @@ Headerless task pop-outs still need a visible drag affordance. The embedded task
overflow: hidden;
}
+/*
+FNXC:FloatingWindow 2026-07-21-00:00:
+Tablet task-detail popups prioritize symmetric content insets over desktop resize affordances. Their body removes the desktop scrollbar-clearance gutter only while all resize handles are suppressed; desktop retains the clearance and resize-safe handles, and the delegated task header remains draggable.
+*/
+@media (min-width: 769px) and (max-width: 1024px) {
+ .floating-window--task-detail .floating-window__body {
+ margin-inline-end: 0;
+ }
+
+ .floating-window--task-detail .floating-window__resize-handle {
+ display: none;
+ }
+}
+
/*
FNXC:ChatModal 2026-06-22-14:49:
On mobile/narrow app viewports, opening Quick Chat should present the full Chat modal as a full-screen sheet instead of a small draggable desktop window. Scope this to the chat FloatingWindow and override the inline desktop geometry only at the mobile breakpoint; desktop pop-out behavior remains movable/resizable.
diff --git a/packages/dashboard/app/components/__tests__/FloatingWindow.test.tsx b/packages/dashboard/app/components/__tests__/FloatingWindow.test.tsx
index e603e352d0..d86269dc37 100644
--- a/packages/dashboard/app/components/__tests__/FloatingWindow.test.tsx
+++ b/packages/dashboard/app/components/__tests__/FloatingWindow.test.tsx
@@ -70,6 +70,20 @@ function stripAtMediaBlocks(css: string): string {
return out;
}
+function mediaBlockFor(css: string, query: string): string {
+ const start = css.indexOf(`@media ${query}`);
+ if (start === -1) return "";
+ const open = css.indexOf("{", start);
+ let depth = 1;
+ let index = open + 1;
+ while (index < css.length && depth > 0) {
+ if (css[index] === "{") depth++;
+ else if (css[index] === "}") depth--;
+ index++;
+ }
+ return css.slice(open + 1, index - 1);
+}
+
function setSheetViewport(isSheetWidth: boolean): void {
vi.stubGlobal("matchMedia", vi.fn((query: string) => ({
matches: query === "(max-width: 768px)" ? isSheetWidth : query === "(max-height: 480px)",
@@ -182,6 +196,47 @@ describe("FloatingWindow", () => {
expect(cssRuleFor(floatingWindowCss, ".floating-window--chat.floating-window--headerless .floating-window__body")).toContain("overflow: hidden;");
});
+ it("removes only tablet task-detail resize clearance and handles for empty and populated popups", () => {
+ const tabletBlock = mediaBlockFor(floatingWindowCss, "(min-width: 769px) and (max-width: 1024px)");
+ const mobileBlock = mediaBlockFor(floatingWindowCss, "(max-width: 768px)");
+ const desktopCss = stripAtMediaBlocks(floatingWindowCss);
+
+ expect(cssRuleFor(tabletBlock, ".floating-window--task-detail .floating-window__body")).toContain("margin-inline-end: 0;");
+ expect(cssRuleFor(tabletBlock, ".floating-window--task-detail .floating-window__resize-handle")).toContain("display: none;");
+ expect(desktopCss.match(/(?:^|\n)\.floating-window__body\s*\{[^}]*\}/)?.[0]).toContain("margin-inline-end: var(--space-lg);");
+ expect(cssRulesForClass(desktopCss, "floating-window--task-detail").some((rule) => /margin-inline-end|display:\s*none/.test(rule))).toBe(false);
+
+ // Mobile remains a full-screen sheet with its independent no-gutter/no-handle contract.
+ expect(cssRuleFor(mobileBlock, ".floating-window--task-detail")).toContain("width: 100vw !important;");
+ expect(cssRuleFor(mobileBlock, ".floating-window--task-detail")).toContain("border-radius: 0;");
+ expect(cssRuleFor(mobileBlock, ".floating-window--task-detail .floating-window__body")).toContain("margin-inline-end: 0;");
+ expect(cssRuleFor(mobileBlock, ".floating-window--task-detail .floating-window__resize-handle")).toContain("display: none;");
+ expect(mobileBlock).toContain(".floating-window--task-detail .task-detail-content--embedded > .modal-header");
+ expect(mobileBlock).toContain("cursor: default;");
+ expect(mobileBlock).toContain("touch-action: auto;");
+
+ Object.defineProperty(window, "innerWidth", { configurable: true, value: 834 });
+ Object.defineProperty(window, "innerHeight", { configurable: true, value: 1112 });
+ setSheetViewport(false);
+ render(
+ <>
+ Scrollable detail {index}
Scrollable task detail {index}
); const { unmount } = render( @@ -950,6 +1005,6 @@ describe("FloatingWindow", () => { expect(mobileBlock).toContain("width: 100vw !important;"); expect(mobileBlock).toContain("height: 100dvh !important;"); expect(mobileBlock).toContain(".floating-window--chat .floating-window__resize-handle"); - expect(floatingWindowCss).not.toMatch(/@media\s*\(min-width:\s*769px\)[\s\S]*\.floating-window--chat[\s\S]*100dvh/); + expect(mediaBlockFor(floatingWindowCss, "(min-width: 769px) and (max-width: 1024px)")).not.toContain(".floating-window--chat"); }); });