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:
@@ -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 && (
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -117,6 +117,8 @@ export function useTerminal(sessionId: string | null): UseTerminalReturn {
|
||||
const buffer = initialBufferRef.current;
|
||||
if (buffer.connected) {
|
||||
callback(buffer.connected);
|
||||
// Clear after replay to prevent stale re-delivery to subsequent subscribers
|
||||
buffer.connected = null;
|
||||
}
|
||||
return () => onConnectCallbacksRef.current.delete(callback);
|
||||
}, []);
|
||||
@@ -127,6 +129,8 @@ export function useTerminal(sessionId: string | null): UseTerminalReturn {
|
||||
const buffer = initialBufferRef.current;
|
||||
if (buffer.scrollback) {
|
||||
callback(buffer.scrollback);
|
||||
// Clear after replay to prevent stale re-delivery to subsequent subscribers
|
||||
buffer.scrollback = null;
|
||||
}
|
||||
return () => onScrollbackCallbacksRef.current.delete(callback);
|
||||
}, []);
|
||||
|
||||
@@ -3715,6 +3715,21 @@ body {
|
||||
color: var(--status-color-deleted, #f85149);
|
||||
}
|
||||
|
||||
/* Task-specific changes header: stacked title + stats layout */
|
||||
.task-changes-tab .task-changes-header-title {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.task-changes-tab .task-changes-header-title h4 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.task-changes-tab .task-changes-stats {
|
||||
margin-left: calc(16px + var(--space-sm)); /* align with text after icon + gap */
|
||||
}
|
||||
|
||||
.changes-file-path {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
Reference in New Issue
Block a user