FN-6774: remove colored card edge accents

Remove saturated edge stripes from stuck task and agent cards while preserving state legibility.

- Keep stuck task board cards and list rows on neutral borders with tinted backgrounds and existing status badges.
- Replace agent card status edge accents with subtle state backgrounds and a selected-card inset ring.
- Add CSS regression coverage to prevent colored edge-border variants from returning.

Files changed:
 packages/dashboard/app/components/AgentsView.css   | 46 ++++++++---
 packages/dashboard/app/components/ListView.css     |  5 +-
 packages/dashboard/app/components/TaskCard.css     |  5 +-
 .../__tests__/stuck-and-agent-card-border.test.ts  | 92 ++++++++++++++++++++++
 4 files changed, 133 insertions(+), 15 deletions(-)

Fusion-Task-Id: FN-6774

Fusion-Task-Lineage: da49ca64-2c10-4594-888f-332cf4f9c8c8
This commit is contained in:
gsxdsm
2026-06-20 04:51:57 -07:00
parent c32c925321
commit fec197afdf
4 changed files with 133 additions and 15 deletions

View File

@@ -469,6 +469,10 @@ The base grid keeps a token-sized handle column as the no-JS fallback, while the
gap: var(--space-lg);
}
/*
FNXC:AgentsView 2026-06-20-03:25:
FN-6774 removes the saturated top-edge status stripe from agent board cards. Agent state remains legible through state chips, subtle card background tints, hover feedback, and the neutral card border.
*/
.agent-board-card {
display: flex;
flex-direction: column;
@@ -476,7 +480,6 @@ The base grid keeps a token-sized handle column as the no-JS fallback, while the
padding: var(--space-lg);
background: var(--surface);
border: 1px solid var(--border);
border-top-width: 3px;
border-radius: var(--radius-md);
transition: background var(--transition-fast), border-color var(--transition-fast);
}
@@ -568,17 +571,20 @@ The base grid keeps a token-sized handle column as the no-JS fallback, while the
gap: var(--space-md);
}
/*
FNXC:AgentsView 2026-06-20-03:25:
FN-6774 removes the saturated left-edge status stripe from split-sidebar agent cards. Selection uses a full-card ring and state uses subtle backgrounds/status chips so no single edge becomes the status indicator.
*/
.agent-card {
border: 1px solid var(--border);
border-left-width: 4px;
border-radius: var(--radius-md);
padding: var(--space-lg);
background: var(--surface);
}
.agent-card--selected {
border-left-color: var(--todo) !important;
background: color-mix(in srgb, var(--todo) 8%, transparent);
box-shadow: inset 0 0 0 calc(var(--space-xs) / 4) var(--todo);
}
.agent-card-header {
@@ -909,27 +915,41 @@ The base grid keeps a token-sized handle column as the no-JS fallback, while the
border: 1px solid var(--state-error-border);
}
.agent-board-card--idle,
.agent-board-card--active,
.agent-board-card--paused { border-top-color: var(--state-idle-border); }
.agent-board-card--active {
background: color-mix(in srgb, var(--state-active-border) 6%, var(--surface));
}
.agent-board-card--paused {
background: var(--state-paused-bg);
}
.agent-board-card--running {
border-top-color: var(--state-active-border);
background: var(--state-active-bg);
}
.agent-board-card--error { border-top-color: var(--state-error-border); }
.agent-card--idle,
.agent-card--active,
.agent-card--paused { border-left-color: var(--state-idle-border); }
.agent-board-card--error {
background: var(--state-error-bg);
}
.agent-card--active {
background: color-mix(in srgb, var(--state-active-border) 6%, var(--surface));
}
.agent-card--paused {
background: var(--state-paused-bg);
}
.agent-card--running {
border-left-color: var(--state-active-border);
background: var(--state-active-bg);
}
.agent-card--running:hover {
background: color-mix(in srgb, var(--state-active-border) 20%, var(--card-hover));
}
.agent-card--error { border-left-color: var(--state-error-border); }
.agent-card--error {
background: var(--state-error-bg);
}
/* === FN-1167: Agent Org Chart + Chain of Command === */
.agent-org-chart-shell {

View File

@@ -515,8 +515,11 @@
opacity: 0.55;
}
/*
FNXC:ListView 2026-06-20-03:25:
FN-6774 removes the saturated stuck-task edge stripe from list rows. Keep the subtle triage background and stuck status badge so stuck rows stay distinguishable without changing the neutral row border.
*/
.list-row.stuck {
border-left: 3px solid var(--triage);
background: color-mix(in srgb, var(--triage) 8%, transparent);
}

View File

@@ -337,8 +337,11 @@ The global mobile touch-action reset applies to descendants, and browsers inters
background: color-mix(in srgb, var(--color-warning) 6%, transparent);
}
/*
FNXC:TaskCard 2026-06-20-03:25:
FN-6774 removes the saturated stuck-task edge stripe from board cards. Keep the triage-tinted surface plus the stuck status badge so the state remains legible while the card uses the neutral board border.
*/
.card.stuck {
border-left: 3px solid var(--triage);
background: color-mix(in srgb, var(--triage) 6%, transparent);
}

View File

@@ -0,0 +1,92 @@
import { describe, expect, it } from "vitest";
import { loadAllAppCss } from "../../test/cssFixture";
const css = loadAllAppCss();
type CssRule = {
selector: string;
body: string;
};
function allRules(): CssRule[] {
return Array.from(css.matchAll(/([^{}]+)\{([^{}]*)\}/g), ([, selector, body]) => ({
selector: selector.replace(/\/\*[\s\S]*?\*\//g, "").trim(),
body: body.trim(),
}));
}
function selectorParts(selector: string): string[] {
return selector.split(",").map((part) => part.trim());
}
function rulesFor(selector: string): CssRule[] {
return allRules().filter((rule) => selectorParts(rule.selector).includes(selector));
}
function baseRule(selector: string): string {
const rule = rulesFor(selector).find((candidate) => !candidate.selector.startsWith("@"));
expect(rule, `${selector} should have a CSS rule`).toBeTruthy();
return rule?.body ?? "";
}
function expectNoEmptyVariantShell(selector: string, axis: "border-left-color" | "border-top-color"): void {
for (const rule of rulesFor(selector)) {
const body = rule.body.trim();
expect(body, `${selector} must not leave an empty CSS rule shell`).not.toBe("");
expect(body, `${selector} must not keep a colored edge override`).not.toContain(axis);
expect(
/(background|box-shadow|border:\s*1px\s+solid\s+var\(--border\))/.test(body),
`${selector} rules should either be deleted or carry a non-stripe legibility declaration`,
).toBe(true);
}
}
describe("stuck task and agent card colored edge borders (FN-6774)", () => {
it("keeps stuck task board cards legible without a triage left stripe", () => {
const stuckCard = baseRule(".card.stuck");
expect(stuckCard).not.toContain("border-left: 3px solid var(--triage)");
expect(stuckCard).not.toContain("border-left");
expect(stuckCard).toContain("background: color-mix(in srgb, var(--triage) 6%, transparent)");
expect(baseRule(".card-status-badge.stuck")).toContain("background: var(--status-triage-bg-deep)");
});
it("keeps stuck list rows legible without a triage left stripe", () => {
const stuckRow = baseRule(".list-row.stuck");
expect(stuckRow).not.toContain("border-left: 3px solid var(--triage)");
expect(stuckRow).not.toContain("border-left");
expect(stuckRow).toContain("background: color-mix(in srgb, var(--triage) 8%, transparent)");
expect(baseRule(".list-status-badge.stuck")).toContain("background: color-mix(in srgb, var(--triage) 20%, transparent)");
});
it("uses neutral split-sidebar agent card borders across agent states", () => {
const agentCard = baseRule(".agent-card");
const selectedCard = baseRule(".agent-card--selected");
expect(agentCard).toContain("border: 1px solid var(--border)");
expect(agentCard).not.toContain("border-left-width: 4px");
expect(selectedCard).not.toContain("border-left-color: var(--todo)");
expect(selectedCard).not.toContain("!important");
expect(selectedCard).toContain("box-shadow: inset 0 0 0 calc(var(--space-xs) / 4) var(--todo)");
for (const state of ["active", "paused", "running", "error"]) {
expectNoEmptyVariantShell(`.agent-card--${state}`, "border-left-color");
}
expect(css).not.toMatch(/\.agent-card--(?:idle|active|paused|running|error)\b[^{}]*\{[^}]*border-left-color/s);
});
it("uses neutral grid agent board card borders across agent states", () => {
const boardCard = baseRule(".agent-board-card");
expect(boardCard).toContain("border: 1px solid var(--border)");
expect(boardCard).not.toContain("border-top-width: 3px");
for (const state of ["active", "paused", "running", "error"]) {
expectNoEmptyVariantShell(`.agent-board-card--${state}`, "border-top-color");
}
expect(css).not.toMatch(/\.agent-board-card--(?:idle|active|paused|running|error)\b[^{}]*\{[^}]*border-top-color/s);
});
});