Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions frontend/src/v2/__tests__/v2-layout-invariants.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5041,16 +5041,28 @@ describe('task priority and lease signals (TASK-443)', () => {
expect(badge).toContain('var(--v2-font-mono)');
expect(badge).toContain('border-radius: 4px');
expect(badge).toContain('background: none');
expect(badge).toContain('color: var(--v2-prio-ink)');
expect(badge).toContain('border: 1px solid var(--v2-prio-edge)');
// P0 is the only filled badge: red fill, white label (B-lite, Sam 10-31).
const urgent = ruleBody(css, '.v2-board__priority--p0');
expect(urgent).toContain('border-color: var(--v2-text-primary)');
expect(urgent).toContain('color: var(--v2-text-primary)');
expect(urgent).not.toMatch(/background/);
expect(urgent).toContain('background: var(--v2-prio-p0-bg)');
expect(urgent).toContain('color: var(--v2-prio-p0-fg)');
// Status and priority colour are tokens, so the D215 colour choice is a value swap.
expect(css).toMatch(/--v2-prio-p0-bg:\s*#b42318/);
expect(css).toMatch(/--v2-prio-p2-fg:\s*#667085/);
expect(css).toMatch(/--v2-status-live:\s*var\(--v2-accent\)/);
expect(ruleBody(css, '.v2-board__priority--p2')).toContain('color: var(--v2-prio-p2-fg)');
});
test('blocked is red with a thin edge on blocked cards only', () => {
expect(css).toMatch(/--v2-status-blocked:\s*#d92d20/);
expect(ruleBody(css, '.v2-board__card--blocked')).toContain('box-shadow: inset 3px 0 0 var(--v2-status-blocked-edge)');
expect(ruleBody(css, '.v2-board__col--blocked .v2-board__col-name')).toContain('color: var(--v2-status-blocked)');
});
test('live, unclaimed and expired ownership retain distinct dots', () => {
expect(ruleBody(css, '.v2-board__owner-dot--live')).toContain('background: var(--v2-accent)');
expect(ruleBody(css, '.v2-board__owner-dot--not-claimed')).toContain('border: 1px dashed var(--v2-border-strong)');
expect(ruleBody(css, '.v2-board__owner-dot--live')).toContain('background: var(--v2-status-live)');
expect(ruleBody(css, '.v2-board__owner-dot--not-claimed')).toContain('border: 1px dashed var(--v2-status-pending)');
const expired = ruleBody(css, '.v2-board__owner-dot--expired');
expect(expired).toContain('border: 1px solid var(--v2-border-strong)');
expect(expired).toContain('border: 1px solid var(--v2-status-idle)');
expect(expired).toContain('background: none');
});
});
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/v2/components/V2PodBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ const V2PodBoard: React.FC = () => {
{COLUMNS.map((col) => {
const items = columnTasks.get(col.key) || [];
return (
<section key={col.key} className="v2-board__col" aria-label={t(col.labelKey)}>
<section key={col.key} className={`v2-board__col${col.key === 'blocked' ? ' v2-board__col--blocked' : ''}`} aria-label={t(col.labelKey)}>
<div className="v2-board__col-head">
<span className="v2-board__col-name">{t(col.labelKey)}</span>
<span className="v2-board__col-count">{items.length}</span>
Expand All @@ -744,7 +744,7 @@ const V2PodBoard: React.FC = () => {
<div className="v2-board__col-empty">{t(col.emptyKey)}</div>
)}
{items.map((task) => (
<article key={task.taskId} className={`v2-board__card${col.key === 'done' ? ' v2-board__card--done' : ''}`}>
<article key={task.taskId} className={`v2-board__card${col.key === 'done' ? ' v2-board__card--done' : ''}${col.key === 'blocked' ? ' v2-board__card--blocked' : ''}`}>
<button
type="button"
className="v2-board__card-main"
Expand All @@ -753,7 +753,7 @@ const V2PodBoard: React.FC = () => {
>
<span className="v2-board__card-kicker">
<span className="v2-board__card-id">{task.taskId}</span>
<span className={`v2-board__priority${task.priority === 'P0' ? ' v2-board__priority--p0' : ''}`}>{task.priority || 'P2'}</span>
<span className={`v2-board__priority${task.priority === 'P0' ? ' v2-board__priority--p0' : ''}${(task.priority || 'P2') === 'P2' ? ' v2-board__priority--p2' : ''}`}>{task.priority || 'P2'}</span>
</span>
<span className="v2-board__card-title">{task.title}</span>
{ownerLine(task)}
Expand Down
41 changes: 35 additions & 6 deletions frontend/src/v2/v2.css
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,20 @@ body.modern-ui.v2-canvas {
--v2-danger: #ef4444;
--v2-danger-text: #b91c1c;
--v2-danger-soft: rgba(239, 68, 68, 0.10);
/* TASK-687/698: board status and priority colour, the D215 B-lite choice (Sam,
10-31). Blocked and P0 are red; in progress stays cobalt; P1, P2, pending and
done stay grey, with no green. Each state keeps its shape. Dark values are in
both dark blocks below. */
--v2-prio-p0-bg: #b42318;
--v2-prio-p0-fg: #ffffff;
--v2-prio-ink: var(--v2-text-secondary);
--v2-prio-p2-fg: #667085;
--v2-prio-edge: var(--v2-border);
--v2-status-live: var(--v2-accent);
--v2-status-idle: var(--v2-border-strong);
--v2-status-pending: #667085;
--v2-status-blocked: #d92d20;
--v2-status-blocked-edge: #d92d20;

/* Agent role colors */
--v2-pink: #f472b6;
Expand Down Expand Up @@ -198,6 +212,12 @@ body.modern-ui.v2-canvas {
--v2-border: #364051;
--v2-border-soft: #262d3a;
--v2-border-strong: #5f6979;
--v2-prio-p0-bg: #f97066;
--v2-prio-p0-fg: #0b0e13;
--v2-prio-p2-fg: #8b94a5;
--v2-status-pending: var(--v2-border-strong);
--v2-status-blocked: #f97066;
--v2-status-blocked-edge: #f97066;
--v2-text-primary: #e8ebf1;
--v2-message-text: #e8ebf1;
--v2-text-secondary: #aeb6c4;
Expand Down Expand Up @@ -244,6 +264,12 @@ body.modern-ui.v2-canvas {
--v2-border: #364051;
--v2-border-soft: #262d3a;
--v2-border-strong: #5f6979;
--v2-prio-p0-bg: #f97066;
--v2-prio-p0-fg: #0b0e13;
--v2-prio-p2-fg: #8b94a5;
--v2-status-pending: var(--v2-border-strong);
--v2-status-blocked: #f97066;
--v2-status-blocked-edge: #f97066;
--v2-text-primary: #e8ebf1;
--v2-message-text: #e8ebf1;
--v2-text-secondary: #aeb6c4;
Expand Down Expand Up @@ -13522,19 +13548,22 @@ body.modern-ui.v2-canvas {
.v2-board__priority {
display: inline-block;
padding: 0 5px;
border: 1px solid var(--v2-border);
border: 1px solid var(--v2-prio-edge);
border-radius: 4px;
font: 500 11px/16px var(--v2-font-mono);
color: var(--v2-text-secondary);
color: var(--v2-prio-ink);
background: none;
}
.v2-board__priority--p0 { border-color: var(--v2-text-primary); color: var(--v2-text-primary); }
.v2-board__priority--p0 { background: var(--v2-prio-p0-bg); border-color: var(--v2-prio-p0-bg); color: var(--v2-prio-p0-fg); }
.v2-board__priority--p2 { color: var(--v2-prio-p2-fg); }
.v2-board__col--blocked .v2-board__col-name { color: var(--v2-status-blocked); }
.v2-board__card--blocked { box-shadow: inset 3px 0 0 var(--v2-status-blocked-edge); }
.v2-board__card-title { font-size: 14px; line-height: 20px; }
.v2-board__owner-line { display: flex; align-items: center; gap: 6px; font: 500 11px/16px var(--v2-font-mono); color: var(--v2-text-secondary); }
.v2-board__owner-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.v2-board__owner-dot--live { background: var(--v2-accent); }
.v2-board__owner-dot--not-claimed { border: 1px dashed var(--v2-border-strong); }
.v2-board__owner-dot--expired { border: 1px solid var(--v2-border-strong); background: none; }
.v2-board__owner-dot--live { background: var(--v2-status-live); }
.v2-board__owner-dot--not-claimed { border: 1px dashed var(--v2-status-pending); }
.v2-board__owner-dot--expired { border: 1px solid var(--v2-status-idle); background: none; }
.v2-board__card--done { border-color: var(--v2-border-soft); }
.v2-board__card--done .v2-board__card-title { color: var(--v2-text-secondary); }
.v2-root button.v2-board__card-move { min-height: 32px; padding: 0 10px; border-radius: 4px; }
Expand Down
Loading