From b3ed63dae92535ec48a1092231765189f75ba368 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Sat, 11 Jul 2026 21:15:13 -0700 Subject: [PATCH] FN-7836: fix Task Documents sidebar cards collapsing to blank rows under flex shrink Fixes the Task Documents view rendering blank/border-only rows once many task-card groups load in the scrolling sidebar; each card now opts out of flex shrink so overflow clipping no longer compresses group content out of view. - DocumentsView.css: add `flex: 0 0 auto` to `.documents-task-sidebar-group` so cards keep their natural height instead of being shrunk by the flex column when many groups are loaded - DocumentsView.test.tsx: add regression test rendering 54 loaded task-document groups, asserting `flex-shrink: 0` and that group heading/content text remains visible and interactive - Add changeset documenting the patch-level fix Files changed: .changeset/fn-7836-task-documents-rendering.md | 7 +++ .../dashboard/app/components/DocumentsView.css | 4 ++ .../components/__tests__/DocumentsView.test.tsx | 71 ++++++++++++++++++++++ 3 files changed, 82 insertions(+) Fusion-Task-Id: FN-7836 Fusion-Task-Lineage: f07bad59-c6b9-41e3-9475-5a4339044bb4 Co-authored-by: Fusion (runfusion.ai) --- .../fn-7836-task-documents-rendering.md | 7 ++ .../app/components/DocumentsView.css | 4 ++ .../__tests__/DocumentsView.test.tsx | 71 +++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 .changeset/fn-7836-task-documents-rendering.md diff --git a/.changeset/fn-7836-task-documents-rendering.md b/.changeset/fn-7836-task-documents-rendering.md new file mode 100644 index 0000000000..d9732cdebc --- /dev/null +++ b/.changeset/fn-7836-task-documents-rendering.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Fix the Artifacts Task Documents list rendering as blank rows when documents are loaded. +category: fix +dev: Root cause was flex-shrinking task cards in DocumentsView.css; cards now opt out of shrink and DocumentsView.test.tsx covers loaded 50+ group rendering. diff --git a/packages/dashboard/app/components/DocumentsView.css b/packages/dashboard/app/components/DocumentsView.css index beb4167786..186c1de259 100644 --- a/packages/dashboard/app/components/DocumentsView.css +++ b/packages/dashboard/app/components/DocumentsView.css @@ -373,6 +373,9 @@ FN-7811 reuses the Project Files shell for Task Documents, while task-scoped sid FNXC:DocumentsView 2026-07-11-19:03: FN-7834 requires task-document groups to scan as discrete task containers, not a flat sequence of peer rows. Keep the stronger card/header hierarchy and inter-group gap scoped under .documents-task-documents-sidebar so Project Files' shared .markdown-file-item list and the Artifacts gallery remain visually unchanged. + +FNXC:DocumentsView 2026-07-11-21:12: +FN-7836 requires loaded Task Documents to render visible task-card groups even when 50+ tasks exist. The sidebar is a scrolling flex column; each card must opt out of flex shrink before overflow is clipped, otherwise browser layout compresses every group into border-only lines while the DOM/text still exists. */ .documents-task-documents-sidebar { display: flex; @@ -383,6 +386,7 @@ FN-7834 requires task-document groups to scan as discrete task containers, not a } .documents-task-sidebar-group { + flex: 0 0 auto; overflow: hidden; border: thin solid var(--border); border-radius: var(--radius-lg); diff --git a/packages/dashboard/app/components/__tests__/DocumentsView.test.tsx b/packages/dashboard/app/components/__tests__/DocumentsView.test.tsx index 008ffdfaff..bb905b0af0 100644 --- a/packages/dashboard/app/components/__tests__/DocumentsView.test.tsx +++ b/packages/dashboard/app/components/__tests__/DocumentsView.test.tsx @@ -439,6 +439,77 @@ describe("DocumentsView", () => { expect(legacyGroup.querySelector(".documents-group-status")).not.toBeInTheDocument(); }); + /* + FNXC:DocumentsView 2026-07-11-21:12: + FN-7836 regression coverage targets the browser-only failure mode: real data can load while 50+ flexed task-card groups shrink under overflow clipping into border-only lines. Keep the test tied to the task-scoped CSS contract (`flex-shrink: 0`) plus visible group/row content so a loaded-but-blank sidebar cannot recur without failing close to the defect. + */ + it("renders many loaded task-document groups without flex-shrinking cards into blank lines", async () => { + const manyTaskDocuments: TaskDocumentWithTask[] = Array.from({ length: 54 }, (_, index) => { + const taskNumber = String(index + 1).padStart(3, "0"); + return { + id: `many-doc-${taskNumber}`, + taskId: `FN-MANY-${taskNumber}`, + key: index === 0 ? "plan" : "notes", + content: `Document content ${taskNumber}`, + revision: index + 1, + author: "agent", + createdAt: `2026-04-19T10:${String(index % 60).padStart(2, "0")}:00.000Z`, + updatedAt: `2026-04-19T12:${String(index % 60).padStart(2, "0")}:00.000Z`, + taskTitle: index === 53 ? undefined : `Loaded task ${taskNumber}`, + taskColumn: index === 52 || index === 53 ? undefined : index % 2 === 0 ? "done" : "todo", + }; + }); + manyTaskDocuments.push({ + id: "many-doc-001-notes", + taskId: "FN-MANY-001", + key: "notes", + content: "Second document content", + revision: 2, + author: "agent", + createdAt: "2026-04-19T09:00:00.000Z", + updatedAt: "2026-04-19T11:59:00.000Z", + taskTitle: "Loaded task 001", + taskColumn: "done", + }); + + mockUseProjectMarkdownFiles.mockReturnValue({ + files: [], + loading: false, + error: null, + refresh: vi.fn().mockResolvedValue(undefined), + }); + mockUseDocuments.mockReturnValue({ + documents: manyTaskDocuments, + projectFiles: [], + loading: false, + error: null, + refresh: vi.fn().mockResolvedValue(undefined), + }); + + render(); + fireEvent.click(screen.getByRole("tab", { name: /show task documents/i })); + + const sidebar = screen.getByLabelText("Task documents"); + const groups = Array.from(sidebar.querySelectorAll(".documents-task-sidebar-group")); + expect(groups).toHaveLength(54); + expect(screen.queryByText("Loading task documents…")).not.toBeInTheDocument(); + expect(screen.queryByText("No task documents yet.")).not.toBeInTheDocument(); + expect(screen.getByText("Select a task document to view its content.")).toBeInTheDocument(); + + const firstGroup = screen.getByRole("heading", { name: /FN-MANY-001.*Loaded task 001/i }).closest(".documents-task-sidebar-group") as HTMLElement; + expect(getComputedStyle(firstGroup).flexShrink).toBe("0"); + expect(within(firstGroup).getByText("FN-MANY-001")).toHaveTextContent("FN-MANY-001"); + expect(within(firstGroup).getByText("Loaded task 001")).toHaveTextContent("Loaded task 001"); + expect(within(firstGroup).getAllByRole("button", { name: /open FN-MANY-001/i })).toHaveLength(2); + + const legacyGroup = screen.getByRole("heading", { name: /FN-MANY-054.*Untitled/i }).closest(".documents-task-sidebar-group") as HTMLElement; + expect(within(legacyGroup).getByText("Untitled")).toBeInTheDocument(); + expect(legacyGroup.querySelector(".documents-group-status")).not.toBeInTheDocument(); + + fireEvent.click(within(firstGroup).getByRole("button", { name: "Open FN-MANY-001 plan" })); + expect(await screen.findByText("Document content 001")).toBeInTheDocument(); + }); + it("selecting a task document loads content and marks the sidebar entry current", () => { render();