diff --git a/docs/dashboard-guide.md b/docs/dashboard-guide.md index 08715b2f21..057dd6dfe2 100644 --- a/docs/dashboard-guide.md +++ b/docs/dashboard-guide.md @@ -77,7 +77,7 @@ Features: - Task card header meta badges group priority, fast mode, agent-created provenance, and elapsed/created-time chips into one wrapping row; agent labels prefer `sourceMetadata.agentName` over raw agent IDs - Column ordering semantics: `todo` mirrors scheduler pickup order (priority descending, then oldest `createdAt`, then task ID); `triage`, `in-progress`, `in-review`, and `archived` remain priority-first with task-ID tie-breaks; `done` is ordered by most recent completion first (`columnMovedAt`, then `updatedAt`, then `createdAt` fallback) - On mobile, both default and workflow-mode boards fill the project viewport while the column strip remains the internal horizontal scroller with contained edge overscroll. -- Board and List workflow switchers use a themed dropdown instead of a native select. The closed trigger shows the workflow name and chevron only; compact Todo / In Progress / Done counts derived from workflow column flags (excluding archived columns) appear while the dropdown is expanded, including on each workflow option. +- Board and List workflow switchers use a themed dropdown instead of a native select. The closed trigger shows the workflow name and chevron only; compact Todo / In Progress / Done counts derived from workflow column flags (excluding archived columns) appear while the dropdown is expanded, including on each workflow option. Those inline count badges intentionally use the same board column color tokens as cards: `--todo`, `--in-progress`, and `--done`. - When workflow columns are enabled, Board and List hydrate the last successful workflow-lane payload from a per-project session cache; cold loads show a neutral skeleton until settings and workflow metadata are known, avoiding a legacy single-lane flash. ![Board view](./screenshots/dashboard-overview.png) diff --git a/packages/dashboard/app/components/WorkflowSwitcher.css b/packages/dashboard/app/components/WorkflowSwitcher.css index fa3a507360..d2b2ab5f3a 100644 --- a/packages/dashboard/app/components/WorkflowSwitcher.css +++ b/packages/dashboard/app/components/WorkflowSwitcher.css @@ -91,16 +91,20 @@ line-height: calc(var(--space-md) / var(--space-sm)); } +/* +FNXC:WorkflowSwitcher 2026-06-20-00:00: +The switcher's inline Todo, In Progress, and Done count badges intentionally mirror the board column color tokens so each count reads as the same color as the column it summarizes. +*/ .workflow-switcher-count--todo { - color: var(--text-muted); + color: var(--todo); } .workflow-switcher-count--in-progress { - color: var(--color-warning); + color: var(--in-progress); } .workflow-switcher-count--done { - color: var(--color-success); + color: var(--done); } .workflow-switcher-count-separator { diff --git a/packages/dashboard/app/components/__tests__/WorkflowSwitcher.test.tsx b/packages/dashboard/app/components/__tests__/WorkflowSwitcher.test.tsx index b18af3819b..0625f4f7f7 100644 --- a/packages/dashboard/app/components/__tests__/WorkflowSwitcher.test.tsx +++ b/packages/dashboard/app/components/__tests__/WorkflowSwitcher.test.tsx @@ -1,6 +1,7 @@ import { fireEvent, render, screen, within } from "@testing-library/react"; import { describe, expect, it, vi } from "vitest"; import type { BoardWorkflowDefinition } from "../../api"; +import { loadAllAppCssBaseOnly } from "../../test/cssFixture"; import { WorkflowSwitcher } from "../WorkflowSwitcher"; import type { WorkflowStatusCounts } from "../workflowStatusCounts"; @@ -21,6 +22,11 @@ function countMap(entries: Array<[string, WorkflowStatusCounts]> = []) { return new Map(entries); } +function cssRuleFor(css: string, selector: string) { + const escaped = selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + return css.match(new RegExp(`${escaped}\\s*\\{([^}]*)\\}`))?.[1] ?? ""; +} + describe("WorkflowSwitcher", () => { it("renders the active workflow without compact counts while collapsed", () => { render( @@ -109,4 +115,20 @@ describe("WorkflowSwitcher", () => { expect(within(designOption).getByText("0", { selector: ".workflow-switcher-count--in-progress" })).toBeInTheDocument(); expect(within(designOption).getByText("0", { selector: ".workflow-switcher-count--done" })).toBeInTheDocument(); }); + + it("colors status counts with board column color tokens", () => { + const css = loadAllAppCssBaseOnly(); + const badgeRules = [ + [".workflow-switcher-count--todo", "--todo"], + [".workflow-switcher-count--in-progress", "--in-progress"], + [".workflow-switcher-count--done", "--done"], + ] as const; + + for (const [selector, token] of badgeRules) { + const rule = cssRuleFor(css, selector); + expect(rule).toMatch(new RegExp(`color:\\s*var\\(${token}\\)`)); + expect(rule).not.toMatch(/var\(--(?:text-muted|color-warning|color-success)\)/); + expect(rule).not.toMatch(/#[0-9a-fA-F]{3,8}|rgba?\(/); + } + }); });