From 80130966f81913a44bd56a71071831e06fab8bfc Mon Sep 17 00:00:00 2001 From: Fusion Date: Mon, 11 May 2026 10:49:33 -0700 Subject: [PATCH] feat(FN-4016): convert hardcoded rgba colors to CSS token variables across Migrated dashboard component CSS from hardcoded `rgba()` values to design token variables across nine components including `CustomModelDropdown`, `CliBinaryPanel`, and `CliBinaryInstallBanner`, with test coverage added for the affected components. Fusion-Task-Id: FN-4016 --- ...board-component-color-tokenization.test.ts | 39 +++++++++++++ .../app/components/AgentReflectionsTab.css | 2 +- .../components/BackgroundTasksIndicator.css | 2 +- .../app/components/CliBinaryInstallBanner.css | 32 +++++------ .../app/components/CliBinaryPanel.css | 52 ++++++++--------- .../app/components/CustomModelDropdown.css | 56 +++++++++---------- .../app/components/FileMentionPopup.css | 6 +- .../app/components/GitHubImportModal.css | 16 +++--- .../app/components/InlineCreateCard.css | 6 +- .../dashboard/app/components/ScriptsModal.css | 16 +++--- .../app/components/WorkspaceSelector.css | 2 +- .../__tests__/AgentReflectionsTab.test.tsx | 8 +++ .../__tests__/GitHubImportModal.test.tsx | 10 ++++ .../__tests__/WorkspaceSelector.test.tsx | 8 +++ 14 files changed, 160 insertions(+), 95 deletions(-) create mode 100644 packages/dashboard/app/__tests__/dashboard-component-color-tokenization.test.ts diff --git a/packages/dashboard/app/__tests__/dashboard-component-color-tokenization.test.ts b/packages/dashboard/app/__tests__/dashboard-component-color-tokenization.test.ts new file mode 100644 index 000000000..877f38174 --- /dev/null +++ b/packages/dashboard/app/__tests__/dashboard-component-color-tokenization.test.ts @@ -0,0 +1,39 @@ +import { describe, expect, it } from "vitest"; +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; + +const root = resolve(__dirname, "../components"); + +const auditedCompliant = ["ChatView.css", "MobileNavBar.css", "ListView.css", "WorkflowResultsTab.css"]; +const cleanedFiles = [ + "ScriptsModal.css", + "InlineCreateCard.css", + "FileMentionPopup.css", + "BackgroundTasksIndicator.css", + "CliBinaryPanel.css", + "CliBinaryInstallBanner.css", + "GitHubImportModal.css", + "WorkspaceSelector.css", + "AgentReflectionsTab.css", +]; + +describe("dashboard component color tokenization", () => { + it("keeps audited compliant files free of raw rgba()", () => { + for (const file of auditedCompliant) { + const source = readFileSync(resolve(root, file), "utf8"); + expect(source).not.toMatch(/rgba\(/); + } + }); + + it("keeps cleaned files free of raw rgba()", () => { + for (const file of cleanedFiles) { + const source = readFileSync(resolve(root, file), "utf8"); + expect(source).not.toMatch(/rgba\(/); + } + }); + + it("keeps CustomModelDropdown free of raw rgba()", () => { + const source = readFileSync(resolve(root, "CustomModelDropdown.css"), "utf8"); + expect(source).not.toMatch(/rgba\(/); + }); +}); diff --git a/packages/dashboard/app/components/AgentReflectionsTab.css b/packages/dashboard/app/components/AgentReflectionsTab.css index f76609dfa..161988cbe 100644 --- a/packages/dashboard/app/components/AgentReflectionsTab.css +++ b/packages/dashboard/app/components/AgentReflectionsTab.css @@ -348,7 +348,7 @@ gap: 8px; padding: 8px 12px; border-radius: 6px; - background: var(--state-error-bg, rgba(248,81,73,0.15)); + background: var(--state-error-bg, color-mix(in srgb, var(--color-error) 15%, transparent)); color: var(--state-error-text, #f85149); border: 1px solid var(--state-error-border, #f85149); font-size: 0.875rem; diff --git a/packages/dashboard/app/components/BackgroundTasksIndicator.css b/packages/dashboard/app/components/BackgroundTasksIndicator.css index 223721d0c..e01032520 100644 --- a/packages/dashboard/app/components/BackgroundTasksIndicator.css +++ b/packages/dashboard/app/components/BackgroundTasksIndicator.css @@ -43,7 +43,7 @@ background: var(--surface); border: 1px solid var(--border); border-radius: 8px; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + box-shadow: var(--shadow-md); z-index: 1000; overflow: hidden; } diff --git a/packages/dashboard/app/components/CliBinaryInstallBanner.css b/packages/dashboard/app/components/CliBinaryInstallBanner.css index a8ffe9f4e..56d5905db 100644 --- a/packages/dashboard/app/components/CliBinaryInstallBanner.css +++ b/packages/dashboard/app/components/CliBinaryInstallBanner.css @@ -6,10 +6,10 @@ padding: 12px 16px; background: linear-gradient( 90deg, - rgba(59, 130, 246, 0.12), - rgba(59, 130, 246, 0.04) + color-mix(in srgb, var(--todo) 12%, transparent), + color-mix(in srgb, var(--todo) 4%, transparent) ); - border: 1px solid rgba(59, 130, 246, 0.35); + border: 1px solid color-mix(in srgb, var(--todo) 35%, transparent); border-radius: 8px; } @@ -24,7 +24,7 @@ .cli-binary-banner__title { font-weight: 600; font-size: 14px; - color: var(--text-primary, #e6edf3); + color: var(--text); } .cli-binary-banner__text { @@ -34,7 +34,7 @@ } .cli-binary-banner__text code { - background: rgba(255, 255, 255, 0.06); + background: color-mix(in srgb, var(--text) 6%, transparent); padding: 1px 6px; border-radius: 4px; font-size: 0.92em; @@ -59,7 +59,7 @@ .cli-binary-banner__primary { background: var(--accent, #3b82f6); - color: #fff; + color: var(--accent-text); } .cli-binary-banner__primary:hover:not(:disabled) { @@ -72,22 +72,22 @@ } .cli-binary-banner__secondary { - background: rgba(255, 255, 255, 0.04); - color: var(--text-primary, #e6edf3); - border-color: rgba(255, 255, 255, 0.12); + background: color-mix(in srgb, var(--text) 4%, transparent); + color: var(--text); + border-color: color-mix(in srgb, var(--text) 12%, transparent); } .cli-binary-banner__secondary:hover { - background: rgba(255, 255, 255, 0.08); + background: color-mix(in srgb, var(--text) 8%, transparent); } .cli-binary-banner__error { margin-top: 4px; padding: 6px 10px; - background: rgba(218, 54, 51, 0.1); - border-left: 3px solid rgba(218, 54, 51, 0.55); - border-radius: 0 4px 4px 0; - color: #f7c4c2; + background: color-mix(in srgb, var(--color-error) 10%, transparent); + border-left: 3px solid color-mix(in srgb, var(--color-error) 55%, transparent); + border-radius: 0 var(--radius-sm) var(--radius-sm) 0; + color: var(--color-error); font-size: 12.5px; line-height: 1.5; } @@ -108,6 +108,6 @@ } .cli-binary-banner__dismiss:hover { - background: rgba(255, 255, 255, 0.06); - color: var(--text-primary, #e6edf3); + background: color-mix(in srgb, var(--text) 6%, transparent); + color: var(--text); } diff --git a/packages/dashboard/app/components/CliBinaryPanel.css b/packages/dashboard/app/components/CliBinaryPanel.css index 78a420930..a62875613 100644 --- a/packages/dashboard/app/components/CliBinaryPanel.css +++ b/packages/dashboard/app/components/CliBinaryPanel.css @@ -34,21 +34,21 @@ } .cli-binary-pill--ok { - background: rgba(46, 160, 67, 0.18); - color: #57c97a; - border: 1px solid rgba(46, 160, 67, 0.4); + background: color-mix(in srgb, var(--color-success) 18%, transparent); + color: var(--color-success); + border: 1px solid color-mix(in srgb, var(--color-success) 40%, transparent); } .cli-binary-pill--warn { - background: rgba(210, 153, 34, 0.18); - color: #e3b341; - border: 1px solid rgba(210, 153, 34, 0.4); + background: color-mix(in srgb, var(--color-warning) 18%, transparent); + color: var(--color-warning); + border: 1px solid color-mix(in srgb, var(--color-warning) 40%, transparent); } .cli-binary-pill--err { - background: rgba(218, 54, 51, 0.18); - color: #f48581; - border: 1px solid rgba(218, 54, 51, 0.4); + background: color-mix(in srgb, var(--color-error) 18%, transparent); + color: var(--color-error); + border: 1px solid color-mix(in srgb, var(--color-error) 40%, transparent); } .cli-binary-help { @@ -57,7 +57,7 @@ } .cli-binary-help code { - background: rgba(255, 255, 255, 0.06); + background: color-mix(in srgb, var(--text) 6%, transparent); padding: 1px 6px; border-radius: 4px; font-size: 0.92em; @@ -69,7 +69,7 @@ } .cli-binary-status-line code { - background: rgba(255, 255, 255, 0.06); + background: color-mix(in srgb, var(--text) 6%, transparent); padding: 1px 6px; border-radius: 4px; } @@ -103,7 +103,7 @@ } .cli-binary-info-list code { - background: rgba(255, 255, 255, 0.06); + background: color-mix(in srgb, var(--text) 6%, transparent); padding: 1px 6px; border-radius: 4px; word-break: break-all; @@ -133,7 +133,7 @@ .cli-binary-install-btn { background: var(--accent, #3b82f6); - color: #fff; + color: var(--accent-text); } .cli-binary-install-btn:hover:not(:disabled) { @@ -148,14 +148,14 @@ .cli-binary-refresh-btn, .cli-binary-copy-btn { - background: rgba(255, 255, 255, 0.04); - color: var(--text-primary, #e6edf3); - border-color: rgba(255, 255, 255, 0.12); + background: color-mix(in srgb, var(--text) 4%, transparent); + color: var(--text); + border-color: color-mix(in srgb, var(--text) 12%, transparent); } .cli-binary-refresh-btn:hover:not(:disabled), .cli-binary-copy-btn:hover { - background: rgba(255, 255, 255, 0.08); + background: color-mix(in srgb, var(--text) 8%, transparent); } .cli-binary-commands { @@ -175,8 +175,8 @@ display: flex; align-items: center; gap: 8px; - background: rgba(0, 0, 0, 0.25); - border: 1px solid rgba(255, 255, 255, 0.06); + background: color-mix(in srgb, var(--bg) 25%, transparent); + border: 1px solid color-mix(in srgb, var(--text) 6%, transparent); border-radius: 6px; padding: 6px 8px 6px 12px; } @@ -191,7 +191,7 @@ } .cli-binary-install-log { - border-top: 1px solid rgba(255, 255, 255, 0.06); + border-top: 1px solid color-mix(in srgb, var(--text) 6%, transparent); padding-top: 10px; font-size: 12.5px; } @@ -204,7 +204,7 @@ .cli-binary-install-output { margin: 6px 0 0; padding: 8px 10px; - background: rgba(0, 0, 0, 0.35); + background: color-mix(in srgb, var(--bg) 35%, transparent); border-radius: 4px; max-height: 220px; overflow: auto; @@ -214,16 +214,16 @@ } .cli-binary-install-output--err { - color: #f48581; + color: var(--color-error); } .cli-binary-permissions-hint { margin: 6px 0; padding: 8px 10px; - background: rgba(218, 54, 51, 0.1); - border-left: 3px solid rgba(218, 54, 51, 0.55); - border-radius: 0 4px 4px 0; - color: #f7c4c2; + background: color-mix(in srgb, var(--color-error) 10%, transparent); + border-left: 3px solid color-mix(in srgb, var(--color-error) 55%, transparent); + border-radius: 0 var(--radius-sm) var(--radius-sm) 0; + color: var(--color-error); font-size: 12.5px; line-height: 1.5; } diff --git a/packages/dashboard/app/components/CustomModelDropdown.css b/packages/dashboard/app/components/CustomModelDropdown.css index e9d2e8496..4493707d8 100644 --- a/packages/dashboard/app/components/CustomModelDropdown.css +++ b/packages/dashboard/app/components/CustomModelDropdown.css @@ -153,12 +153,12 @@ } .model-combobox-option--selected { - background: rgba(88, 166, 255, 0.15); + background: color-mix(in srgb, var(--todo) 15%, transparent); } .model-combobox-option--selected:hover, .model-combobox-option--selected.model-combobox-option--highlighted { - background: rgba(88, 166, 255, 0.25); + background: color-mix(in srgb, var(--todo) 25%, transparent); } .model-combobox-option-main { @@ -380,22 +380,22 @@ html .column.drag-over * { --status-color-unknown: #6e7781; /* Shadow for light mode */ - --shadow-sm: 0 1px 2px rgba(31, 35, 40, 0.08); - --shadow-md: 0 4px 6px rgba(31, 35, 40, 0.12); - --shadow-lg: 0 4px 24px rgba(31, 35, 40, 0.15); - --shadow-glow: 0 0 8px rgba(9, 105, 218, 0.18); - --glow-success: 0 0 8px rgba(26, 127, 55, 0.3); - --glow-warning: 0 0 8px rgba(154, 103, 0, 0.3); - --glow-danger: 0 0 8px rgba(207, 34, 46, 0.3); - --focus-ring: 0 0 0 2px rgba(9, 105, 218, 0.12); - --focus-ring-strong: 0 0 0 2px rgba(9, 105, 218, 0.24); + --shadow-sm: 0 1px 2px color-mix(in srgb, var(--text) 8%, transparent); + --shadow-md: 0 4px 6px color-mix(in srgb, var(--text) 12%, transparent); + --shadow-lg: 0 4px 24px color-mix(in srgb, var(--text) 15%, transparent); + --shadow-glow: 0 0 8px color-mix(in srgb, var(--todo) 18%, transparent); + --glow-success: 0 0 8px color-mix(in srgb, var(--color-success) 30%, transparent); + --glow-warning: 0 0 8px color-mix(in srgb, var(--color-warning) 30%, transparent); + --glow-danger: 0 0 8px color-mix(in srgb, var(--color-error) 30%, transparent); + --focus-ring: 0 0 0 2px color-mix(in srgb, var(--todo) 12%, transparent); + --focus-ring-strong: 0 0 0 2px color-mix(in srgb, var(--todo) 24%, transparent); /* CTA tokens for light mode */ --cta-bg: #1a7f37; --cta-border: #1f883d; --cta-text: #fff; --cta-bg-hover: #1f883d; --cta-border-hover: #2ea043; - --cta-glow: 0 0 8px rgba(26, 127, 55, 0.3); + --cta-glow: 0 0 8px color-mix(in srgb, var(--color-success) 30%, transparent); /* Info color for light mode */ --color-info: #0969da; @@ -435,7 +435,7 @@ html .column.drag-over * { /* Mission autopilot — darker for light backgrounds */ --autopilot-icon: #ca8a04; - --autopilot-shadow: rgba(34, 197, 94, 0.4); + --autopilot-shadow: color-mix(in srgb, var(--color-success) 40%, transparent); /* Terminal background */ --terminal-bg: #f6f8fa; @@ -443,8 +443,8 @@ html .column.drag-over * { /* Card mission badge — darker purple for light bg */ --badge-mission-text: #7c3aed; --badge-mission-text-hover: #8b5cf6; - --badge-mission-bg: rgba(124, 58, 237, 0.12); - --badge-mission-bg-hover: rgba(124, 58, 237, 0.22); + --badge-mission-bg: color-mix(in srgb, var(--badge-mission-text) 12%, transparent); + --badge-mission-bg-hover: color-mix(in srgb, var(--badge-mission-text-hover) 22%, transparent); /* Mission event type colors — darker/more saturated for light readability */ --event-error-text: #dc2626; @@ -452,15 +452,15 @@ html .column.drag-over * { --event-task-text: #059669; --event-slice-text: #d97706; --event-autopilot-text: #9333ea; - --event-error-bg: rgba(220, 38, 38, 0.12); - --event-state-bg: rgba(37, 99, 235, 0.12); - --event-task-bg: rgba(5, 150, 105, 0.12); - --event-slice-bg: rgba(217, 119, 6, 0.12); - --event-autopilot-bg: rgba(147, 51, 234, 0.12); + --event-error-bg: color-mix(in srgb, var(--event-error-text) 12%, transparent); + --event-state-bg: color-mix(in srgb, var(--event-state-text) 12%, transparent); + --event-task-bg: color-mix(in srgb, var(--event-task-text) 12%, transparent); + --event-slice-bg: color-mix(in srgb, var(--event-slice-text) 12%, transparent); + --event-autopilot-bg: color-mix(in srgb, var(--event-autopilot-text) 12%, transparent); /* Mission toggle & badge backgrounds */ - --toggle-checked-bg: rgba(34, 197, 94, 0.15); - --meta-badge-bg: rgba(63, 185, 80, 0.08); + --toggle-checked-bg: color-mix(in srgb, var(--color-success) 15%, transparent); + --meta-badge-bg: color-mix(in srgb, var(--color-success) 8%, transparent); /* Star favorites */ --star-idle: #9ca3af; @@ -472,19 +472,19 @@ html .column.drag-over * { [data-theme="light"] .agent-detail-overlay, [data-theme="light"] .agent-dialog-overlay, [data-theme="light"] .chat-new-dialog-backdrop { - background: rgba(31, 35, 40, 0.5); + background: color-mix(in srgb, var(--text) 50%, transparent); } [data-theme="light"] .modal-header { - background: rgba(246, 248, 250, 0.8); + background: color-mix(in srgb, var(--surface) 80%, transparent); } [data-theme="light"] .modal-actions { - background: rgba(246, 248, 250, 0.6); + background: color-mix(in srgb, var(--surface) 60%, transparent); } [data-theme="light"] .settings-sidebar { - background: rgba(246, 248, 250, 0.6); + background: color-mix(in srgb, var(--surface) 60%, transparent); } [data-theme="light"] .toast-success { @@ -1062,7 +1062,7 @@ html .column.drag-over * { .theme-swatch-glass { --swatch-sample-1: #13111f; - --swatch-sample-2: rgba(34, 27, 52, 0.78); + --swatch-sample-2: color-mix(in srgb, #221b34 78%, transparent); --swatch-sample-3: #c86bff; --swatch-sample-4: #ff7aa8; } @@ -1273,7 +1273,7 @@ html .column.drag-over * { [data-theme="light"] .theme-swatch-glass { --swatch-sample-1: #eceaf5; - --swatch-sample-2: rgba(255, 255, 255, 0.75); + --swatch-sample-2: color-mix(in srgb, #ffffff 75%, transparent); --swatch-sample-3: #9d40cf; --swatch-sample-4: #c74b7a; } diff --git a/packages/dashboard/app/components/FileMentionPopup.css b/packages/dashboard/app/components/FileMentionPopup.css index 3edb5413e..bbd0a9305 100644 --- a/packages/dashboard/app/components/FileMentionPopup.css +++ b/packages/dashboard/app/components/FileMentionPopup.css @@ -144,7 +144,7 @@ .chat-new-dialog-backdrop { position: fixed; inset: 0; - background: rgba(0, 0, 0, 0.6); + background: color-mix(in srgb, var(--bg) 60%, transparent); backdrop-filter: blur(4px); display: flex; align-items: center; @@ -281,8 +281,8 @@ } .chat-new-dialog-agent-item--selected { - background: var(--accent-color-light, rgba(59, 130, 246, 0.1)); - border: 1px solid var(--accent-color, rgba(59, 130, 246, 0.3)); + background: color-mix(in srgb, var(--todo) 10%, transparent); + border: 1px solid color-mix(in srgb, var(--todo) 30%, transparent); } .chat-new-dialog-agent-name { diff --git a/packages/dashboard/app/components/GitHubImportModal.css b/packages/dashboard/app/components/GitHubImportModal.css index 5974f6014..3e7cf7574 100644 --- a/packages/dashboard/app/components/GitHubImportModal.css +++ b/packages/dashboard/app/components/GitHubImportModal.css @@ -40,7 +40,7 @@ .github-import-toolbar__zone--filter input:focus { border-color: var(--color-primary); - box-shadow: 0 0 0 2px rgba(var(--color-primary-rgb), 0.2); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-primary) 20%, transparent); outline: none; } @@ -106,7 +106,7 @@ .github-import-remote-select select:focus { outline: none; border-color: var(--color-primary); - box-shadow: 0 0 0 2px rgba(var(--color-primary-rgb), 0.2); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-primary) 20%, transparent); } /* Load button */ @@ -540,8 +540,8 @@ } .issue-item.selected { - background: rgba(var(--in-progress-rgb), 0.12); - box-shadow: inset 0 0 0 1px rgba(var(--in-progress-rgb), 0.35); + background: color-mix(in srgb, var(--in-progress) 12%, transparent); + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--in-progress) 35%, transparent); } .issue-item.imported { @@ -653,7 +653,7 @@ [data-theme="light"] .github-import-tab.active { background: var(--card); border-color: var(--border); - box-shadow: 0 1px 3px rgba(31, 35, 40, 0.06); + box-shadow: var(--shadow-sm); } [data-theme="light"] .github-import-toolbar { @@ -668,7 +668,7 @@ [data-theme="light"] .github-import-toolbar__zone--filter input:focus { border-color: var(--color-primary, var(--todo)); - box-shadow: 0 0 0 2px rgba(var(--in-progress-rgb), 0.15); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--in-progress) 15%, transparent); } [data-theme="light"] .issues-list { @@ -681,8 +681,8 @@ } [data-theme="light"] .issue-item.selected { - background: rgba(var(--in-progress-rgb), 0.08); - box-shadow: inset 0 0 0 1px rgba(var(--in-progress-rgb), 0.3); + background: color-mix(in srgb, var(--in-progress) 8%, transparent); + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--in-progress) 30%, transparent); } [data-theme="light"] .issue-item.imported input[type="radio"] { diff --git a/packages/dashboard/app/components/InlineCreateCard.css b/packages/dashboard/app/components/InlineCreateCard.css index 473ca056f..fd40c49e0 100644 --- a/packages/dashboard/app/components/InlineCreateCard.css +++ b/packages/dashboard/app/components/InlineCreateCard.css @@ -189,8 +189,8 @@ display: flex; align-items: center; justify-content: center; - background: rgba(0, 0, 0, 0.6); - color: #fff; + background: color-mix(in srgb, var(--bg) 60%, transparent); + color: var(--text); border: none; border-radius: 50%; width: 16px; @@ -203,7 +203,7 @@ } .inline-create-preview-remove:hover { - background: rgba(248, 81, 73, 0.9); + background: color-mix(in srgb, var(--color-error) 90%, transparent); } .inline-create-model-wrap { diff --git a/packages/dashboard/app/components/ScriptsModal.css b/packages/dashboard/app/components/ScriptsModal.css index 4274a0434..80ae7091d 100644 --- a/packages/dashboard/app/components/ScriptsModal.css +++ b/packages/dashboard/app/components/ScriptsModal.css @@ -3940,16 +3940,16 @@ .changes-diff-patch .diff-add, .gm-diff-patch [data-prefix="+"], .changes-diff-patch [data-prefix="+"] { - color: #3fb950; - background-color: rgba(63, 185, 80, 0.12); + color: var(--color-success); + background-color: color-mix(in srgb, var(--color-success) 12%, transparent); } .gm-diff-patch .diff-del, .changes-diff-patch .diff-del, .gm-diff-patch [data-prefix="-"], .changes-diff-patch [data-prefix="-"] { - color: #f85149; - background-color: rgba(248, 81, 73, 0.12); + color: var(--color-error); + background-color: color-mix(in srgb, var(--color-error) 12%, transparent); } .gm-diff-patch .diff-hunk, @@ -3976,16 +3976,16 @@ [data-theme="light"] .changes-diff-patch .diff-add, [data-theme="light"] .gm-diff-patch [data-prefix="+"], [data-theme="light"] .changes-diff-patch [data-prefix="+"] { - color: #1a7f37; - background-color: rgba(26, 127, 55, 0.1); + color: var(--color-success); + background-color: color-mix(in srgb, var(--color-success) 10%, transparent); } [data-theme="light"] .gm-diff-patch .diff-del, [data-theme="light"] .changes-diff-patch .diff-del, [data-theme="light"] .gm-diff-patch [data-prefix="-"], [data-theme="light"] .changes-diff-patch [data-prefix="-"] { - color: #cf222e; - background-color: rgba(207, 34, 46, 0.1); + color: var(--color-error); + background-color: color-mix(in srgb, var(--color-error) 10%, transparent); } [data-theme="light"] .gm-diff-patch .diff-hunk, diff --git a/packages/dashboard/app/components/WorkspaceSelector.css b/packages/dashboard/app/components/WorkspaceSelector.css index 3c0a3b45b..93be25a54 100644 --- a/packages/dashboard/app/components/WorkspaceSelector.css +++ b/packages/dashboard/app/components/WorkspaceSelector.css @@ -89,7 +89,7 @@ } .workspace-selector-option.active { - background: rgba(88, 166, 255, 0.12); + background: color-mix(in srgb, var(--todo) 12%, transparent); } .workspace-selector-option-main { diff --git a/packages/dashboard/app/components/__tests__/AgentReflectionsTab.test.tsx b/packages/dashboard/app/components/__tests__/AgentReflectionsTab.test.tsx index b6ffabd81..bd93086d5 100644 --- a/packages/dashboard/app/components/__tests__/AgentReflectionsTab.test.tsx +++ b/packages/dashboard/app/components/__tests__/AgentReflectionsTab.test.tsx @@ -1,6 +1,8 @@ import { describe, it, expect, beforeEach, vi } from "vitest"; import { render, screen, fireEvent, waitFor } from "@testing-library/react"; import { AgentReflectionsTab } from "../AgentReflectionsTab"; +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; import { addAgentRating, deleteAgentRating, @@ -281,4 +283,10 @@ describe("AgentReflectionsTab", () => { expect(screen.queryByText("Insights")).not.toBeInTheDocument(); }); }); + + it("keeps budget warning banner tokenized", () => { + const source = readFileSync(resolve(__dirname, "../AgentReflectionsTab.css"), "utf8"); + expect(source).toMatch(/\.budget-warning-banner\s*\{[^}]*var\(--state-error-bg, color-mix\(in srgb, var\(--color-error\) 15%, transparent\)\)/); + expect(source).not.toMatch(/\.budget-warning-banner\s*\{[^}]*rgba\(/); + }); }); diff --git a/packages/dashboard/app/components/__tests__/GitHubImportModal.test.tsx b/packages/dashboard/app/components/__tests__/GitHubImportModal.test.tsx index 08d97c92d..ecc4b0b05 100644 --- a/packages/dashboard/app/components/__tests__/GitHubImportModal.test.tsx +++ b/packages/dashboard/app/components/__tests__/GitHubImportModal.test.tsx @@ -10,6 +10,8 @@ import { } from "../../api"; import type { Task } from "@fusion/core"; import type { GitRemote } from "../../api"; +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; // Mock the API module vi.mock("../../api", async (importOriginal) => { @@ -68,6 +70,14 @@ describe("GitHubImportModal", () => { const onClose = vi.fn(); const onImport = vi.fn(); + it("uses color-mix tokens for focus and selection surfaces", () => { + const source = readFileSync(resolve(__dirname, "../GitHubImportModal.css"), "utf8"); + expect(source).not.toContain("rgba(var(--color-primary-rgb)"); + expect(source).not.toContain("rgba(var(--in-progress-rgb)"); + expect(source).toContain("color-mix(in srgb, var(--in-progress) 12%, transparent)"); + expect(source).toContain("Some hardcoded colors below"); + }); + beforeEach(() => { vi.clearAllMocks(); vi.mocked(fetchGitRemotes).mockReset(); diff --git a/packages/dashboard/app/components/__tests__/WorkspaceSelector.test.tsx b/packages/dashboard/app/components/__tests__/WorkspaceSelector.test.tsx index f1974e587..ca9cfb686 100644 --- a/packages/dashboard/app/components/__tests__/WorkspaceSelector.test.tsx +++ b/packages/dashboard/app/components/__tests__/WorkspaceSelector.test.tsx @@ -4,6 +4,8 @@ import userEvent from "@testing-library/user-event"; import { WorkspaceSelector } from "../WorkspaceSelector"; import type { WorkspaceInfo } from "../../hooks/useWorkspaces"; import { loadAllAppCss } from "../../test/cssFixture"; +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; const workspaces: WorkspaceInfo[] = [ { @@ -96,4 +98,10 @@ describe("WorkspaceSelector", () => { expect(css).toMatch(/\.workspace-selector-menu\s*\{[^}]*left:\s*auto;[^}]*right:\s*0;/); }); + + it("uses tokenized active-option background styling", () => { + const source = readFileSync(resolve(__dirname, "../WorkspaceSelector.css"), "utf8"); + expect(source).toMatch(/\.workspace-selector-option\.active\s*\{[^}]*color-mix\(in srgb, var\(--todo\) 12%, transparent\)/); + expect(source).not.toMatch(/\.workspace-selector-option\.active\s*\{[^}]*rgba\(/); + }); });