diff --git a/packages/dashboard/app/components/TaskDetailModal.tsx b/packages/dashboard/app/components/TaskDetailModal.tsx index 7fe4580d38..6c0bfd7806 100644 --- a/packages/dashboard/app/components/TaskDetailModal.tsx +++ b/packages/dashboard/app/components/TaskDetailModal.tsx @@ -659,12 +659,12 @@ export function TaskDetailContent({ // Reset description expanded state when task changes useEffect(() => { - setDescriptionExpanded(false); - }, [task.id]); + setDescriptionExpanded(task.column === "triage"); + }, [task.column, task.id]); const [logSubview, setLogSubview] = useState<"activity" | "agent-log">("activity"); const [highlightStallCode, setHighlightStallCode] = useState(null); - const [descriptionExpanded, setDescriptionExpanded] = useState(false); + const [descriptionExpanded, setDescriptionExpanded] = useState(() => task.column === "triage"); const [attachments, setAttachments] = useState(task.attachments || []); const [uploading, setUploading] = useState(false); const [dependencies, setDependencies] = useState(task.dependencies || []); diff --git a/packages/dashboard/app/components/__tests__/TaskDetailModal.rendering.test.tsx b/packages/dashboard/app/components/__tests__/TaskDetailModal.rendering.test.tsx index bccaa831e3..0c4acc6c41 100644 --- a/packages/dashboard/app/components/__tests__/TaskDetailModal.rendering.test.tsx +++ b/packages/dashboard/app/components/__tests__/TaskDetailModal.rendering.test.tsx @@ -1300,6 +1300,54 @@ describe("TaskDetailModal", () => { }); describe("description truncation", () => { + it("expands long triage title by default with Show less button", () => { + const longTitle = "Triage title ".repeat(25); + const { container } = render( + , + ); + + const h2 = container.querySelector("h2.detail-title"); + expect(h2?.textContent).toBe(longTitle); + const toggle = container.querySelector(".detail-description-toggle"); + expect(toggle?.textContent).toBe("Show less"); + }); + + it("expands long triage description by default when title is missing", () => { + const longDescription = "Triage description ".repeat(20); + const { container } = render( + , + ); + + const h2 = container.querySelector("h2.detail-title"); + expect(h2?.textContent).toBe(longDescription); + const toggle = container.querySelector(".detail-description-toggle"); + expect(toggle?.textContent).toBe("Show less"); + }); + it("truncates description over 200 characters with Show more button", () => { const longDescription = "A".repeat(250); const { container } = render( @@ -1350,6 +1398,43 @@ describe("TaskDetailModal", () => { expect(toggle.textContent).toBe("Show less"); }); + it("lets Show less and Show more override the triage default for the current task", async () => { + const longDescription = "C".repeat(250); + const { container } = render( + , + ); + + const toggle = container.querySelector(".detail-description-toggle") as HTMLButtonElement; + expect(container.querySelector("h2.detail-title")?.textContent).toBe("C".repeat(250)); + expect(toggle.textContent).toBe("Show less"); + + await act(async () => { + fireEvent.click(toggle); + }); + + expect(container.querySelector("h2.detail-title")?.textContent).toBe("C".repeat(200) + "…"); + expect(toggle.textContent).toBe("Show more"); + + await act(async () => { + fireEvent.click(toggle); + }); + + expect(container.querySelector("h2.detail-title")?.textContent).toBe("C".repeat(250)); + expect(toggle.textContent).toBe("Show less"); + }); + it("collapses description when Show less is clicked", async () => { const longDescription = "C".repeat(250); const { container } = render( @@ -1383,6 +1468,29 @@ describe("TaskDetailModal", () => { expect(toggle.textContent).toBe("Show more"); }); + it("does not show toggle for empty title and description fallback to task id", () => { + const { container } = render( + , + ); + + const h2 = container.querySelector("h2.detail-title"); + expect(h2?.textContent).toBe("FN-EMPTY"); + expect(container.querySelector(".detail-description-toggle")).toBeNull(); + }); + it("does not show toggle for description under 200 characters", () => { const shortDescription = "Short description"; const { container } = render( @@ -1449,6 +1557,52 @@ describe("TaskDetailModal", () => { expect(toggle?.textContent).toBe("Show more"); }); + it("resets to expanded when switching from a non-triage task to a triage task", async () => { + const todoDescription = "G".repeat(250); + const triageDescription = "H".repeat(250); + const { container, rerender } = render( + , + ); + + expect(container.querySelector("h2.detail-title")?.textContent).toBe("G".repeat(200) + "…"); + expect(container.querySelector(".detail-description-toggle")?.textContent).toBe("Show more"); + + rerender( + , + ); + + await waitFor(() => { + expect(container.querySelector("h2.detail-title")?.textContent).toBe("H".repeat(250)); + }); + expect(container.querySelector(".detail-description-toggle")?.textContent).toBe("Show less"); + }); + it("resets expanded state when task changes", async () => { const longDescription1 = "E".repeat(250); const longDescription2 = "F".repeat(250); diff --git a/packages/dashboard/app/components/__tests__/TaskDetailModal.test-helpers.ts b/packages/dashboard/app/components/__tests__/TaskDetailModal.test-helpers.ts index 54a77bd518..72f0f32778 100644 --- a/packages/dashboard/app/components/__tests__/TaskDetailModal.test-helpers.ts +++ b/packages/dashboard/app/components/__tests__/TaskDetailModal.test-helpers.ts @@ -69,6 +69,17 @@ vi.mock("lucide-react", () => ({ GitMerge: () => null, GitBranch: () => null, AlertTriangle: () => null, + Play: () => null, + Flag: () => null, + Terminal: () => null, + Shield: () => null, + PauseCircle: () => null, + Split: () => null, + Merge: () => null, + Repeat: () => null, + ClipboardCheck: () => null, + ListChecks: () => null, + Code2: () => null, })); vi.mock("../../hooks/useAgentLogs", () => ({