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:
5
.changeset/fn-6688-text-primary-cleanup.md
Normal file
5
.changeset/fn-6688-text-primary-cleanup.md
Normal 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.
|
||||
@@ -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`).
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
max-width: 480px;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
color: var(--text-primary);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.error-boundary--root {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
}
|
||||
|
||||
.skill-chip-remove:hover:not(:disabled) {
|
||||
color: var(--text-primary);
|
||||
color: var(--text);
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1258,7 +1258,7 @@ body {
|
||||
}
|
||||
|
||||
.modal-send-to-background:hover {
|
||||
color: var(--text-primary);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.modal-send-to-background:focus-visible {
|
||||
|
||||
Reference in New Issue
Block a user