FN-7240: Make task-detail tool text readable

Raise task-detail chat tool-call typography while preserving compact collapsed rows.

- Increase task chat tool summary, kicker, label, and detail text to the base spacing font token.
- Add CSS regression coverage to prevent the smaller calc font size from returning across desktop, mobile, and narrow hosts.
- Include the TaskChatTab suite in the dashboard chat quality test lane and add a patch changeset.

Files changed:
 .changeset/fn-7240-task-chat-tool-font.md          |  7 ++++++
 packages/dashboard/app/components/TaskChatTab.css  | 11 ++++++----
 .../app/components/__tests__/TaskChatTab.test.tsx  | 25 +++++++++++++++++++---
 packages/dashboard/vitest.config.ts                |  2 ++
 4 files changed, 38 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-7240

Fusion-Task-Lineage: 4d3ed287-27b7-4107-bc42-0119d5a4f1e9

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-06-29 14:29:17 -07:00
parent a766813ed9
commit e80d85b101
4 changed files with 38 additions and 7 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Make task-detail Chat tool-call text easier to read without expanding collapsed rows.
category: fix
dev: TaskChatTab tool-call summary, kicker, label, and detail typography now use the readable base spacing token.

View File

@@ -283,6 +283,9 @@ FN-7207 makes the right-side dock and narrow desktop detail hosts use the same r
/*
FNXC:TaskChat 2026-06-28-00:00:
FN-7215 aligns task-detail tool-call summaries with regular Chat's compact collapsed treatment. Keep the clickable row token-sized, single-line by default, and ellipsis-friendly so completed tool history does not dominate task transcripts while details remain available through native <details> expansion.
FNXC:TaskChat 2026-06-29-14:00:
FN-7240 raises the FN-7225 follow-up tool-call typography to the readable base spacing token while preserving FN-7215's compact collapsed summary treatment, so task-detail summaries, counts, names, and errors inherit consistent sizing without expanding their padding.
*/
.task-chat-tool-group-summary {
min-width: 0;
@@ -291,7 +294,7 @@ FN-7215 aligns task-detail tool-call summaries with regular Chat's compact colla
padding: var(--space-xs);
color: var(--text-muted);
border-radius: var(--radius-sm);
font-size: calc(var(--space-md) - (var(--space-xs) + (var(--space-xs) / 4)));
font-size: var(--space-md);
}
.task-chat-tool-group-summary::-webkit-details-marker,
@@ -382,7 +385,7 @@ FN-7215 aligns task-detail tool-call summaries with regular Chat's compact colla
.task-chat-entry-kicker {
margin-bottom: calc(var(--space-xs) / 2);
color: var(--text-muted);
font-size: calc(var(--space-md) - (var(--space-xs) + (var(--space-xs) / 4)));
font-size: var(--space-md);
font-weight: 600;
text-transform: none;
letter-spacing: normal;
@@ -412,7 +415,7 @@ FN-7215 aligns task-detail tool-call summaries with regular Chat's compact colla
.task-chat-tool-detail-label {
color: var(--text-muted);
font-size: calc(var(--space-md) - (var(--space-xs) + (var(--space-xs) / 4)));
font-size: var(--space-md);
font-weight: 600;
}
@@ -424,7 +427,7 @@ FN-7215 aligns task-detail tool-call summaries with regular Chat's compact colla
overflow-x: auto;
white-space: pre-wrap;
word-break: break-word;
font-size: calc(var(--space-md) - (var(--space-xs) + (var(--space-xs) / 4)));
font-size: var(--space-md);
}
.task-chat-composer {

View File

@@ -102,6 +102,9 @@ function getCssDeclaration(rule: string, propertyName: string): string {
return declarationMatch?.[1]?.trim() ?? "";
}
const TOO_SMALL_TASK_TOOL_FONT_SIZE = "font-size: calc(var(--space-md) - (var(--space-xs) + (var(--space-xs) / 4)))";
const READABLE_TASK_TOOL_FONT_SIZE = "font-size: var(--space-md)";
function getRootTokenPxValues(css: string): Record<string, number> {
const rootRule = getCssRuleBlock(css, ":root");
const tokenValues: Record<string, number> = {};
@@ -2504,6 +2507,7 @@ describe("TaskChatTab", () => {
expect(narrowHostGroupRule).toContain("grid-template-columns: 1fr");
expect(narrowHostHeaderRule).toContain("min-width: 0");
expect(narrowHostUserEntryRule).toContain("max-width: 100%");
expect(narrowHostCss).not.toContain(TOO_SMALL_TASK_TOOL_FONT_SIZE);
expect(listSplitGroupRule).toContain("grid-template-columns: 1fr");
expect(mobileGroupRule).toContain("grid-template-columns: 1fr");
});
@@ -2597,7 +2601,7 @@ describe("TaskChatTab", () => {
expect(mobileTimestampRule).toContain("white-space: normal");
});
it("keeps task-chat tool summaries compact like regular chat on desktop and mobile", () => {
it("keeps task-chat tool summaries compact and tool text readable on desktop and mobile", () => {
const css = readFileSync(resolve(__dirname, "../TaskChatTab.css"), "utf8");
const chatCss = readFileSync(resolve(__dirname, "../ChatView.css"), "utf8");
const compactCss = getCssAfter(css, "FN-7215 aligns task-detail tool-call summaries");
@@ -2607,6 +2611,8 @@ describe("TaskChatTab", () => {
const errorRule = getCssRuleBlock(css, ".task-chat-tool-group-error-count");
const entriesRule = getCssRuleBlock(getCssAfter(css, ".task-chat-tool-group-entries {\n gap"), ".task-chat-tool-group-entries");
const entryRule = getCssRuleBlock(css, ".task-chat-tool-entry");
const kickerRule = getCssRuleBlock(css, ".task-chat-entry-kicker");
const detailLabelRule = getCssRuleBlock(css, ".task-chat-tool-detail-label");
const detailRule = getCssRuleBlock(getCssAfter(css, ".task-chat-tool-detail {"), ".task-chat-tool-detail");
const chatSummaryRule = getCssRuleBlock(chatCss, ".chat-tool-calls-group-summary");
const chatNamesRule = getCssRuleBlock(chatCss, ".chat-tool-calls-names");
@@ -2617,7 +2623,7 @@ describe("TaskChatTab", () => {
expect(summaryRule).toContain("flex-wrap: nowrap");
expect(summaryRule).toContain("padding: var(--space-xs)");
expect(summaryRule).toContain("font-size: calc(var(--space-md) - (var(--space-xs) + (var(--space-xs) / 4)))");
expect(summaryRule).toContain(READABLE_TASK_TOOL_FONT_SIZE);
expect(summaryRule).toContain("border-radius: var(--radius-sm)");
expect(summaryRule).not.toContain("px");
expect(summaryRule).not.toContain("#");
@@ -2630,12 +2636,25 @@ describe("TaskChatTab", () => {
expect(errorRule).toContain("white-space: nowrap");
expect(entriesRule).toContain("padding: 0 var(--space-xs) var(--space-xs)");
expect(entryRule).toContain("border-radius: var(--radius-sm)");
expect(detailRule).toContain("font-size: calc(var(--space-md) - (var(--space-xs) + (var(--space-xs) / 4)))");
/*
* FNXC:TaskDetailChat 2026-06-29-14:13:
* FN-7240 regression coverage must fail if task-detail tool-call typography returns to the too-small FN-7225 calc. The summary, kicker, detail label, and detail body all use the readable base token while retaining compact spacing.
*/
for (const [selector, readableToolTextRule] of [
[".task-chat-tool-group-summary", summaryRule],
[".task-chat-entry-kicker", kickerRule],
[".task-chat-tool-detail-label", detailLabelRule],
[".task-chat-tool-detail", detailRule],
] as const) {
expect(readableToolTextRule, `${selector} uses readable tool-call typography`).toContain(READABLE_TASK_TOOL_FONT_SIZE);
expect(readableToolTextRule, `${selector} does not restore the too-small calc`).not.toContain(TOO_SMALL_TASK_TOOL_FONT_SIZE);
}
expect(chatSummaryRule).toContain("padding: var(--space-xs)");
expect(chatSummaryRule).toContain("border-radius: var(--radius-sm)");
expect(chatNamesRule).toContain("text-overflow: ellipsis");
expect(mobileSummaryRule).toContain("flex-direction: row");
expect(mobileSummaryRule).toContain("flex-wrap: nowrap");
expect(mobileCss).not.toContain(TOO_SMALL_TASK_TOOL_FONT_SIZE);
expect(mobileNamesRule).toContain("width: auto");
expect(mobileErrorRule).toContain("width: auto");
});

View File

@@ -252,6 +252,8 @@ const qualityAppChatOnlyTests = [
"app/components/__tests__/ChatView.core.test.tsx",
"app/components/__tests__/ChatView.sessions-rooms.test.tsx",
"app/components/__tests__/ChatView.mobile.test.tsx",
// FNXC:DashboardTests 2026-06-29-14:14: Task-detail chat typography regressions must run in the same chat quality lane as the required FN-7240 targeted command, so CSS-content assertions cannot fall through to broad backfill only.
"app/components/__tests__/TaskChatTab.test.tsx",
];
const qualityAppSettingsOnlyTests = [
"app/components/__tests__/SettingsModal.general.test.tsx",