FN-6688: replace dashboard primary text alias

Replace undefined dashboard primary text aliases with the canonical theme-aware text token.

- Swap non-Command-Center CSS references from `--text-primary` to `--text` across dashboard components.
- Extend text token canonicalization tests to block future `--text-primary` usage and root alias definitions.
- Document the dashboard CSS token rule and add a patch changeset for the published CLI bundle.

Files changed:
 .changeset/fn-6688-text-primary-cleanup.md          |  5 +++++
 docs/dashboard-guide.md                             |  2 ++
 .../__tests__/text-token-canonicalization.test.ts   | 18 ++++++++++++++++--
 .../dashboard/app/components/ActiveAgentsPanel.css  |  4 ++--
 .../dashboard/app/components/CliBinaryPanel.css     |  2 +-
 .../app/components/ConversationHistory.css          |  6 +++---
 .../dashboard/app/components/DesktopLaunchGate.css  |  2 +-
 packages/dashboard/app/components/ErrorBoundary.css |  2 +-
 .../dashboard/app/components/LanguageSelector.css   |  2 +-
 packages/dashboard/app/components/MobileNavBar.css  |  4 ++--
 packages/dashboard/app/components/QuickEntryBox.css |  6 +++---
 packages/dashboard/app/components/ScriptsModal.css  | 21 +++++++++++++--------
 .../dashboard/app/components/SkillMultiselect.css   |  2 +-
 .../dashboard/app/components/TaskFieldsSection.css  |  4 ++--
 .../app/components/WorkflowFieldsPanel.css          |  2 +-
 packages/dashboard/app/styles.css                   |  2 +-
 16 files changed, 55 insertions(+), 29 deletions(-)

Fusion-Task-Id: FN-6688

Fusion-Task-Lineage: 96e47af2-8bf5-4326-be24-2816530fd646
This commit is contained in:
gsxdsm
2026-06-19 01:33:13 -07:00
parent 0f021aee4f
commit 282b06949e
16 changed files with 55 additions and 29 deletions

View File

@@ -0,0 +1,5 @@
---
"@runfusion/fusion": patch
---
Replace non-Command-Center dashboard CSS references to the undefined `--text-primary` alias with the canonical `--text` token so primary text uses the intended theme-aware color.

View File

@@ -1257,6 +1257,8 @@ The `index.html` shell is templated server-side: the server injects a per-user `
Command Center chart surfaces are a stricter token-only zone: `CommandCenter.css`, `areas/areas.css`, and `charts/charts.css` should avoid raw color fallbacks and hardcoded dimensions in component rules, keep secondary copy on `--text-muted`, use canonical `--accent` / `--text` for generic accent and primary text styling, use `--duration-*` for animation durations, and encode mobile chart invariants with shared classes rather than one-off area styles. The undefined `--color-accent` / `--text-primary` aliases are forbidden under `components/command-center/**` and guarded by `command-center-css-token-canonicalization.test.ts`.
Non-Command-Center dashboard CSS uses `--text` as the canonical primary text token. The undefined `--text-primary` alias is forbidden outside `components/command-center/**` and guarded by `packages/dashboard/app/__tests__/text-token-canonicalization.test.ts`.
### Theme system
Dark/light modes via `data-theme`; 54 color themes via `data-color-theme` (lazy-loaded from `app/public/theme-data.css`).

View File

@@ -1,4 +1,4 @@
// Regression guard for FN-4286 follow-up to FN-4195: prevent reintroducing undefined --text-secondary.
// Regression guard for FN-4286/FN-6688: prevent reintroducing undefined primary/secondary text aliases.
import { readFileSync, readdirSync, statSync } from "node:fs";
import path from "node:path";
import { describe, expect, it } from "vitest";
@@ -38,13 +38,27 @@ describe("text token canonicalization", () => {
expect(offenders, `Unexpected --text-secondary references in: ${offenders.join(", ")}`).toEqual([]);
});
it("defines canonical text tokens and does not define --text-secondary at :root", () => {
it("keeps --text-primary out of dashboard source files outside command-center", () => {
const offenders: string[] = [];
for (const relPath of collectSourceFiles(APP_ROOT)) {
if (relPath.startsWith("components/command-center/")) continue;
if (ALLOWLIST.has(relPath)) continue;
const content = readFileSync(path.join(APP_ROOT, relPath), "utf8");
if (content.includes("--text-primary")) offenders.push(relPath);
}
expect(offenders, `Unexpected --text-primary references in: ${offenders.join(", ")}`).toEqual([]);
});
it("defines canonical text tokens and does not define legacy text aliases at :root", () => {
const stylesCss = loadStylesCss();
const rootBlocks = [...stylesCss.matchAll(/:root\s*\{([\s\S]*?)\}/g)].map((match) => match[1]);
expect(rootBlocks.length).toBeGreaterThan(0);
const allRootContent = rootBlocks.join("\n");
expect(allRootContent).not.toMatch(/^\s*--text-primary\s*:/m);
expect(allRootContent).not.toMatch(/^\s*--text-secondary\s*:/m);
expect(allRootContent).toMatch(/^\s*--text\s*:/m);
expect(allRootContent).toMatch(/^\s*--text-muted\s*:/m);
expect(allRootContent).toMatch(/^\s*--text-dim\s*:/m);
});

View File

@@ -79,7 +79,7 @@
.live-agent-card-status {
font-style: normal;
font-weight: 500;
color: var(--text-primary);
color: var(--text);
opacity: 1;
white-space: nowrap;
overflow: hidden;
@@ -153,7 +153,7 @@
.live-agent-card-logs-btn:hover {
background: var(--bg-hover);
color: var(--text-primary);
color: var(--text);
border-color: var(--border-strong, var(--border));
}

View File

@@ -185,7 +185,7 @@
flex: 1;
font-family: var(--font-mono, ui-monospace, "SFMono-Regular", monospace);
font-size: 12.5px;
color: var(--text-primary, #e6edf3);
color: var(--text);
white-space: nowrap;
overflow-x: auto;
}

View File

@@ -34,7 +34,7 @@
border-radius: 999px;
background: color-mix(in srgb, var(--bg-secondary) 80%, transparent);
border: 1px solid var(--border-primary);
color: var(--text-primary);
color: var(--text);
font-size: 11px;
font-weight: 600;
letter-spacing: 0.02em;
@@ -46,7 +46,7 @@
border-radius: 8px;
background: var(--bg-secondary);
padding: 8px 10px;
color: var(--text-primary);
color: var(--text);
display: flex;
flex-direction: column;
gap: 4px;
@@ -99,7 +99,7 @@
.conversation-thinking-toggle:hover {
background: var(--bg-secondary);
color: var(--text-primary);
color: var(--text);
}
.conversation-thinking-toggle:focus-visible {

View File

@@ -5,7 +5,7 @@
align-items: center;
justify-content: center;
background: var(--bg-primary, #0f1117);
color: var(--text-primary, #e5e7eb);
color: var(--text);
z-index: 9999;
padding: 1.5rem;
}

View File

@@ -11,7 +11,7 @@
max-width: 480px;
margin: auto;
text-align: center;
color: var(--text-primary);
color: var(--text);
}
.error-boundary--root {

View File

@@ -25,7 +25,7 @@
border: 1px solid var(--border-color, #333);
border-radius: 6px;
background: var(--bg-secondary, transparent);
color: var(--text-primary, inherit);
color: var(--text);
font-size: 0.875rem;
cursor: pointer;
transition: border-color 0.15s ease, background 0.15s ease;

View File

@@ -96,7 +96,7 @@
}
.mobile-nav-tab:active {
color: var(--text-primary);
color: var(--text);
}
.mobile-nav-tab--active {
@@ -218,7 +218,7 @@
min-height: 36px;
background: none;
border: none;
color: var(--text-primary);
color: var(--text);
font-size: 15px;
cursor: pointer;
transition: background 0.15s ease;

View File

@@ -236,7 +236,7 @@
background: none;
border: none;
border-radius: 6px;
color: var(--text-primary);
color: var(--text);
cursor: pointer;
text-align: left;
font-size: 0.8125rem;
@@ -289,13 +289,13 @@
}
.model-submenu-back:hover {
color: var(--text-primary);
color: var(--text);
}
.model-submenu-header {
font-size: 0.75rem;
font-weight: 600;
color: var(--text-primary);
color: var(--text);
padding-bottom: 4px;
border-bottom: 1px solid var(--border);
}

View File

@@ -1,3 +1,8 @@
/*
FNXC:DashboardStyling 2026-06-19-00:00:
Non-Command-Center dashboard CSS must use the canonical --text token. The legacy primary-text alias was undefined, so it made primary text inherit fallback/parent colors or hardcoded hex colors that ignored the active theme (FN-6688).
*/
/* === Scripts Modal === */
.scripts-modal {
display: flex;
@@ -258,7 +263,7 @@
.schedule-empty-state h4 {
margin: 0;
font-size: 16px;
color: var(--text-primary);
color: var(--text);
}
.schedule-empty-state p {
@@ -317,7 +322,7 @@
.schedule-card-name {
font-weight: 600;
font-size: 14px;
color: var(--text-primary);
color: var(--text);
}
.schedule-type-badge {
@@ -441,7 +446,7 @@
}
.schedule-history-toggle:hover {
color: var(--text-primary);
color: var(--text);
}
.schedule-history-list {
@@ -597,7 +602,7 @@
.schedule-step-result-name {
font-weight: 500;
color: var(--text-primary);
color: var(--text);
}
.schedule-step-result-error {
@@ -695,7 +700,7 @@
flex: 1;
font-size: 12px;
font-weight: 500;
color: var(--text-primary);
color: var(--text);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -865,7 +870,7 @@
.routine-empty-state h4 {
margin: 0;
font-size: 16px;
color: var(--text-primary);
color: var(--text);
}
.routine-empty-state p {
@@ -934,7 +939,7 @@
.routine-card-name {
font-weight: 600;
font-size: 14px;
color: var(--text-primary);
color: var(--text);
}
.routine-trigger-badge {
@@ -1113,7 +1118,7 @@
.routine-trigger-btn:hover {
border-color: var(--border-hover, var(--border));
background: var(--bg-secondary);
color: var(--text-primary);
color: var(--text);
}
.routine-trigger-btn.active {

View File

@@ -54,7 +54,7 @@
}
.skill-chip-remove:hover:not(:disabled) {
color: var(--text-primary);
color: var(--text);
background: var(--bg-hover);
}

View File

@@ -41,7 +41,7 @@
border: 1px solid var(--border-color, #2a2d34);
border-radius: 6px;
background: var(--input-bg, #16181d);
color: var(--text-primary, #e6e6e6);
color: var(--text);
font-size: 13px;
font-family: inherit;
}
@@ -103,7 +103,7 @@
align-items: center;
gap: 6px;
font-size: 13px;
color: var(--text-primary, #e6e6e6);
color: var(--text);
cursor: pointer;
}

View File

@@ -170,7 +170,7 @@
}
.wf-field-color-swatch.is-active {
outline: 2px solid var(--text-primary, #fff);
outline: 2px solid var(--text);
outline-offset: 1px;
}

View File

@@ -1258,7 +1258,7 @@ body {
}
.modal-send-to-background:hover {
color: var(--text-primary);
color: var(--text);
}
.modal-send-to-background:focus-visible {