FN-8527: theme imported task stats links

Make imported-source links in the shared Stats panel follow the active dashboard theme.

- Style imported task links with the dashboard accent and accessible focus treatment.
- Cover safe themed external links across shared Stats surfaces.
- Add a patch changeset for the user-facing visual fix.

Files changed:
 .changeset/fn-8527-themed-stats-link.md            |  7 +++++
 .../app/components/TaskTokenStatsPanel.css         | 15 +++++++++++
 .../app/components/TaskTokenStatsPanel.tsx         |  7 ++++-
 .../__tests__/TaskTokenStatsPanel.test.tsx         | 30 ++++++++++++++++++++++
 4 files changed, 58 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-8527

Fusion-Task-Lineage: c7ee16ea-23e7-462d-a5c6-799fe0ede62d

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-22 22:20:03 -07:00
parent adf51e21d7
commit 25cd42d020
4 changed files with 58 additions and 1 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Make imported task links in Stats follow the active dashboard theme.
category: fix
dev: The shared Stats provenance link now uses the --accent token.

View File

@@ -132,6 +132,21 @@
font-size: calc(var(--space-sm) + var(--space-xs)); font-size: calc(var(--space-sm) + var(--space-xs));
} }
.task-token-stats-panel__imported-source-link {
color: var(--accent);
overflow-wrap: anywhere;
}
.task-token-stats-panel__imported-source-link:hover {
text-decoration: underline;
}
.task-token-stats-panel__imported-source-link:focus-visible {
outline: none;
box-shadow: var(--focus-ring-strong);
border-radius: var(--radius-sm);
}
.task-token-stats-panel__cache-ratio { .task-token-stats-panel__cache-ratio {
color: var(--text); color: var(--text);
font-size: calc(var(--space-sm) + var(--space-xs)); font-size: calc(var(--space-sm) + var(--space-xs));

View File

@@ -317,7 +317,12 @@ export function TaskTokenStatsPanel({ tokenUsage, loading, task }: TaskTokenStat
<dt>{t("taskDetail.provenance.importedFrom", "Imported from")}</dt> <dt>{t("taskDetail.provenance.importedFrom", "Imported from")}</dt>
<dd> <dd>
{/^https?:\/\//i.test(task.sourceMetadata.issueUrl) ? ( {/^https?:\/\//i.test(task.sourceMetadata.issueUrl) ? (
<a href={task.sourceMetadata.issueUrl} target="_blank" rel="noreferrer"> /*
FNXC:TaskStatsProvenance 2026-07-22-21:47:
Imported-source links use the active accent rather than the browser default so the
shared Stats panel remains theme-aware on desktop and narrow/mobile task detail.
*/
<a className="task-token-stats-panel__imported-source-link" href={task.sourceMetadata.issueUrl} target="_blank" rel="noreferrer">
{task.sourceMetadata.issueUrl} {task.sourceMetadata.issueUrl}
</a> </a>
) : ( ) : (

View File

@@ -1,3 +1,5 @@
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { describe, expect, it, vi } from "vitest"; import { describe, expect, it, vi } from "vitest";
import { render, screen } from "@testing-library/react"; import { render, screen } from "@testing-library/react";
import { createInstance } from "i18next"; import { createInstance } from "i18next";
@@ -6,6 +8,8 @@ import { TaskTokenStatsPanel } from "../TaskTokenStatsPanel";
import type { Task } from "@fusion/core"; import type { Task } from "@fusion/core";
import realEnApp from "../../../../i18n/locales/en/app.json"; import realEnApp from "../../../../i18n/locales/en/app.json";
const taskTokenStatsPanelCss = readFileSync(resolve(__dirname, "../TaskTokenStatsPanel.css"), "utf8");
function makeTask(overrides: Partial<Task> = {}): Task { function makeTask(overrides: Partial<Task> = {}): Task {
return { return {
id: "FN-400", id: "FN-400",
@@ -311,6 +315,32 @@ describe("TaskTokenStatsPanel", () => {
.toHaveAttribute("href", "https://github.com/Runfusion/Fusion/issues/2356"); .toHaveAttribute("href", "https://github.com/Runfusion/Fusion/issues/2356");
}); });
/*
FNXC:TaskStatsProvenance 2026-07-22-21:47:
The desktop and narrow/mobile task detail both mount this shared Stats panel. A populated
imported task must keep its safe external-link contract while component CSS binds its color to
the active theme accent instead of browser-default blue.
*/
it("uses the active theme accent for populated imported-source links across shared Stats surfaces", () => {
const issueUrl = "https://github.com/Runfusion/Fusion/issues/2410";
render(<TaskTokenStatsPanel loading={false} tokenUsage={undefined} task={makeTask({
sourceType: "github",
sourceMetadata: { issueUrl },
})} />);
const importedSource = screen.getByRole("link", { name: issueUrl });
expect(importedSource).toHaveClass("task-token-stats-panel__imported-source-link");
expect(importedSource).toHaveAttribute("href", issueUrl);
expect(importedSource).toHaveAttribute("target", "_blank");
expect(importedSource).toHaveAttribute("rel", "noreferrer");
expect(taskTokenStatsPanelCss).toMatch(
/\.task-token-stats-panel__imported-source-link\s*\{[^}]*color:\s*var\(--accent\);[^}]*\}/,
);
expect(taskTokenStatsPanelCss).not.toMatch(
/\.task-token-stats-panel__imported-source-link\s*\{[^}]*color:\s*(?:blue|#[0-9a-f]{3,8}|rgb)/i,
);
});
it("renders a non-http issueUrl as plain text, never as a link", () => { it("renders a non-http issueUrl as plain text, never as a link", () => {
render(<TaskTokenStatsPanel loading={false} tokenUsage={undefined} task={makeTask({ render(<TaskTokenStatsPanel loading={false} tokenUsage={undefined} task={makeTask({
sourceType: "api", sourceType: "api",