From 65822a02b48150dafed421fa94f73259915203fb Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Tue, 30 Jun 2026 21:23:14 -0700 Subject: [PATCH] FN-7333: stabilize Planner Chat expanded spacing Stabilize Planner Chat task detail spacing across expanded and mobile layouts. - Move Planner Chat body padding to the base selector so expand/collapse only changes height and flex behavior. - Apply the mobile Planner Chat padding override to the same base body selector. - Add CSS regression coverage and a patch changeset for the published CLI bundle. Files changed: .changeset/planner-chat-stable-spacing.md | 7 ++++ .../dashboard/app/components/TaskDetailModal.css | 11 +++++- ...etailModal.responsive-and-dependencies.test.tsx | 44 ++++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) Fusion-Task-Id: FN-7333 Fusion-Task-Lineage: 84130908-fabb-433f-a48d-5d9c6649c234 Co-authored-by: Fusion (runfusion.ai) --- .changeset/planner-chat-stable-spacing.md | 7 +++ .../app/components/TaskDetailModal.css | 11 ++++- ...Modal.responsive-and-dependencies.test.tsx | 44 +++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 .changeset/planner-chat-stable-spacing.md diff --git a/.changeset/planner-chat-stable-spacing.md b/.changeset/planner-chat-stable-spacing.md new file mode 100644 index 0000000000..ed71443090 --- /dev/null +++ b/.changeset/planner-chat-stable-spacing.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Keep Planner Chat spacing stable when expanding task details. +category: fix +dev: Stabilizes task-detail Planner Chat CSS so expanded mode changes height allocation without padding jumps. diff --git a/packages/dashboard/app/components/TaskDetailModal.css b/packages/dashboard/app/components/TaskDetailModal.css index 79559fe974..74287242d2 100644 --- a/packages/dashboard/app/components/TaskDetailModal.css +++ b/packages/dashboard/app/components/TaskDetailModal.css @@ -140,6 +140,14 @@ Task detail workflow badges share the board badge's slight token-based icon-to-l padding-block: var(--space-md); } +/* +FNXC:TaskDetailPlannerChat 2026-06-30-23:58: +Planner Chat expand/collapse may reallocate height or hide mobile chrome, but it must not change the chat surface spacing. Keep body padding on the collapsed base selector and let expanded selectors own only flex/height behavior. +*/ +.detail-body--planner-chat { + padding: var(--space-md); +} + .detail-title { font-size: 18px; font-weight: 600; @@ -884,7 +892,6 @@ Expanded Planner Chat must still expose task Priority, Execution Mode, and the t .task-detail-content--planner-chat-expanded .detail-body--planner-chat { flex: 1; min-height: 0; - padding: var(--space-md); } .task-detail-content--planner-chat-expanded .detail-section--planner-chat { @@ -1196,7 +1203,7 @@ FN-6500 fixes a tablet regression from FN-5599: the task-detail overlay offset a margin-bottom: var(--space-sm); } - .task-detail-content--planner-chat-expanded .detail-body--planner-chat { + .detail-body--planner-chat { padding: var(--space-sm); } } diff --git a/packages/dashboard/app/components/__tests__/TaskDetailModal.responsive-and-dependencies.test.tsx b/packages/dashboard/app/components/__tests__/TaskDetailModal.responsive-and-dependencies.test.tsx index bf0c8e88ff..d1664828c3 100644 --- a/packages/dashboard/app/components/__tests__/TaskDetailModal.responsive-and-dependencies.test.tsx +++ b/packages/dashboard/app/components/__tests__/TaskDetailModal.responsive-and-dependencies.test.tsx @@ -63,6 +63,12 @@ function getExactCssRuleBlock(css: string, selector: string): string { return ruleMatch?.[1] ?? ""; } +function getStandaloneCssRuleBlock(css: string, selector: string): string { + const escapedSelector = selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + const ruleMatch = css.match(new RegExp(`(?:^|})\\s*${escapedSelector}\\s*\\{([^}]*)\\}`)); + return ruleMatch?.[1] ?? ""; +} + function getCssAtRuleBlockContainingExactRule(css: string, atRule: string, selector: string): string { let startAt = 0; while (startAt < css.length) { @@ -88,6 +94,12 @@ function expectTabTouchAction(ruleBlock: string, surface: string): void { expect(ruleBlock, `${surface} touch-action`).toContain("touch-action: pan-x pan-y;"); } +function expectNoSpacingOverrides(ruleBlock: string, surface: string): void { + expect(ruleBlock, `${surface} padding`).not.toMatch(/\bpadding(?:-[\w-]+)?:/); + expect(ruleBlock, `${surface} margin`).not.toMatch(/\bmargin(?:-[\w-]+)?:/); + expect(ruleBlock, `${surface} gap`).not.toMatch(/(?:^|\s)gap:/); +} + describe("TaskDetailModal", () => { describe("mobile responsive structure", () => { it("keeps planner chat composer usable on narrow task-detail layouts", () => { @@ -149,6 +161,38 @@ describe("TaskDetailModal", () => { expect(plannerExpandedTabsBlock).toContain("flex: 0 0 auto;"); }); + it("keeps Planner Chat expand spacing identical across desktop and mobile", () => { + const css = readDashboardStylesSource(); + const plannerBodySpacingStart = css.indexOf("Planner Chat expand/collapse may reallocate height"); + expect(plannerBodySpacingStart).toBeGreaterThanOrEqual(0); + const plannerBodySpacingCss = css.slice(plannerBodySpacingStart, css.indexOf(".detail-title", plannerBodySpacingStart)); + const plannerBodyBlock = getExactCssRuleBlock(plannerBodySpacingCss, ".detail-body--planner-chat"); + const plannerPanelBlock = getExactCssRuleBlock(css, ".task-planner-chat"); + const plannerTranscriptBlock = getExactCssRuleBlock(css, ".task-planner-chat-transcript"); + const plannerComposerBlock = getExactCssRuleBlock(css, ".task-planner-chat-composer"); + const expandedPlannerBodyBlock = getExactCssRuleBlock(css, ".task-detail-content--planner-chat-expanded .detail-body--planner-chat"); + const expandedPlannerSectionBlock = getExactCssRuleBlock(css, ".task-detail-content--planner-chat-expanded .detail-section--planner-chat"); + const mobilePlannerBlock = getCssAtRuleBlockContaining(css, "@media (max-width: 768px)", ".task-detail-content--planner-chat-expanded .detail-meta"); + const mobilePlannerBodyBlock = getStandaloneCssRuleBlock(mobilePlannerBlock, ".detail-body--planner-chat"); + const mobileExpandedPlannerBodyBlock = getExactCssRuleBlock(mobilePlannerBlock, ".task-detail-content--planner-chat-expanded .detail-body--planner-chat"); + + expect(plannerBodyBlock).toContain("padding: var(--space-md);"); + expect(expandedPlannerBodyBlock).toContain("flex: 1;"); + expect(expandedPlannerBodyBlock).toContain("min-height: 0;"); + expectNoSpacingOverrides(expandedPlannerBodyBlock, "desktop expanded planner body"); + expect(expandedPlannerSectionBlock).toContain("flex: 1;"); + expect(expandedPlannerSectionBlock).toContain("min-height: 0;"); + expectNoSpacingOverrides(expandedPlannerSectionBlock, "desktop expanded planner section"); + expect(mobilePlannerBodyBlock).toContain("padding: var(--space-sm);"); + expect(mobileExpandedPlannerBodyBlock).toBe(""); + expect(plannerPanelBlock).toContain("gap: var(--space-md);"); + expect(plannerTranscriptBlock).toContain("padding: var(--space-md);"); + expect(plannerTranscriptBlock).toContain("gap: var(--space-md);"); + expect(plannerComposerBlock).toContain("gap: var(--space-sm);"); + expect(css).not.toMatch(/task-detail-content--planner-chat-expanded[^{]+\.(?:task-planner-chat|task-planner-chat-transcript|task-planner-chat-composer)\s*\{[^}]*(?:padding|margin|gap)\s*:/); + expect(css).not.toMatch(/task-detail-content--planner-chat-expanded[^{]+\.detail-body--planner-chat\s*\{[^}]*(?:padding|margin|gap)\s*:/); + }); + it("keeps detail metadata as a single wrapping flex row without mobile column fallbacks", () => { const css = readDashboardStylesSource();