feat(FN-1019): reflow Changes-tab header stats and fix terminal scrollback

- Reflow Changes-tab header stats to a second line for better layout
- Add CSS styles for two-line header stats display
- Fix useTerminal hook to clear buffered scrollback after first subscriber replay
- Add tests for TaskChangesTab header stats rendering
- Update README description for Changes tab header
This commit is contained in:
gsxdsm
2026-04-05 22:58:28 -07:00
parent 904e4c8e00
commit ec33691033
5 changed files with 60 additions and 6 deletions

View File

@@ -196,14 +196,16 @@ export function TaskChangesTab({ taskId, worktree, projectId, column, mergeDetai
)}
<div className="changes-header">
<h4>
<FileCode size={16} />
Files Changed ({stats.filesChanged})
<span className="changes-stat-summary">
<div className="task-changes-header-title">
<h4>
<FileCode size={16} />
Files Changed ({stats.filesChanged})
</h4>
<span className="task-changes-stats changes-stat-summary">
<span className="diff-add">+{stats.additions}</span>{" "}
<span className="diff-del">-{stats.deletions}</span>
</span>
</h4>
</div>
<div className="changes-header-actions-wrapper">
<div className="changes-header-actions">
{files.length > 0 && (

View File

@@ -216,6 +216,39 @@ describe("TaskChangesTab — commit-backed (done tasks)", () => {
expect(screen.getByText("-0")).toBeTruthy();
});
it("renders stat summary on a separate line from Files Changed title", async () => {
mockFetchTaskDiff.mockResolvedValue(DONE_TASK_DIFF);
const { container } = render(
<TaskChangesTab
taskId="FN-001"
worktree={undefined}
column="done"
mergeDetails={MERGE_DETAILS}
/>,
);
await waitFor(() => {
expect(screen.getByText("Files Changed (2)")).toBeTruthy();
});
// The title and stats should be in a dedicated wrapper
const titleWrapper = container.querySelector(".task-changes-header-title");
expect(titleWrapper).toBeTruthy();
// The h4 should contain "Files Changed (N)" but NOT the stat summary
const h4 = titleWrapper?.querySelector("h4");
expect(h4).toBeTruthy();
expect(h4?.textContent).toContain("Files Changed (2)");
expect(h4?.querySelector(".changes-stat-summary")).toBeNull();
// The stat summary should be a sibling of h4, not a child
const statSummary = titleWrapper?.querySelector(".task-changes-stats");
expect(statSummary).toBeTruthy();
expect(statSummary?.querySelector(".diff-add")?.textContent).toBe("+3");
expect(statSummary?.querySelector(".diff-del")?.textContent).toBe("-0");
});
it("toggling file expansion shows/hides diff content", async () => {
mockFetchTaskDiff.mockResolvedValue(DONE_TASK_DIFF);
const { container } = render(