From c9146e15b226d1ba7faa3a8e7cd0e9e4b7cc04bf Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Sun, 21 Jun 2026 11:28:08 -0700 Subject: [PATCH] FN-6830: use theme accent for sidebar active states Align the left sidebar selected and resize states with each active dashboard theme. - Switch active left-sidebar item color and background to the shared --accent token. - Update the resize-handle focus and hover accent to follow theme accent colors. - Add a CSS regression test and documentation for the theme-accent invariant. - Define shared typography tokens and replace an optional-step danger fallback with an existing error token. Files changed: docs/dashboard-guide.md | 2 +- .../left-sidebar-active-accent.css.test.ts | 38 ++++++++++++++++++++++ .../dashboard/app/components/LeftSidebarNav.css | 10 +++--- .../app/components/WorkflowOptionalStepsPanel.css | 2 +- packages/dashboard/app/styles.css | 3 ++ 5 files changed, 48 insertions(+), 7 deletions(-) Fusion-Task-Id: FN-6830 Fusion-Task-Lineage: add8e9cd-4b91-45a1-a848-a54dd1083723 --- docs/dashboard-guide.md | 2 +- .../left-sidebar-active-accent.css.test.ts | 38 +++++++++++++++++++ .../app/components/LeftSidebarNav.css | 10 ++--- .../components/WorkflowOptionalStepsPanel.css | 2 +- packages/dashboard/app/styles.css | 3 ++ 5 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 packages/dashboard/app/__tests__/left-sidebar-active-accent.css.test.ts diff --git a/docs/dashboard-guide.md b/docs/dashboard-guide.md index a66caab865..5061f8464b 100644 --- a/docs/dashboard-guide.md +++ b/docs/dashboard-guide.md @@ -27,7 +27,7 @@ When enabled on desktop or tablet project screens, the sidebar contains the prim While the sidebar is active on desktop/tablet project screens, Board and List workflow controls move into the Header slot that replaces the hidden view toggle. Board and List share one workflow dropdown: each workflow row includes an inline edit action, and a persistent **New workflow** action remains at the bottom of the dropdown while the workflow list scrolls. The standalone workflow row above the board/list content is removed in this mode. When the flag is off, outside project screens, or on mobile, workflow controls remain inline with the same consolidated dropdown. -The footer collapse toggle uses the same row styling as other sidebar items: expanded mode shows a **Collapse** label, while collapsed rail mode hides the label and keeps the icon-only button accessible through its label/title. The expanded width can still be resized from the right-edge separator. Collapsed state and expanded width are saved in browser `localStorage` (`fusion:left-sidebar-collapsed` and `fusion:left-sidebar-width`) and restored on reload. +The footer collapse toggle uses the same row styling as other sidebar items: expanded mode shows a **Collapse** label, while collapsed rail mode hides the label and keeps the icon-only button accessible through its label/title. The active nav-item highlight and the resize-handle hover/focus accent track the active color theme's `--accent` token across all themes, so shadcn, forest, ocean, and other themes no longer show a fixed blue selected state. The expanded width can still be resized from the right-edge separator. Collapsed state and expanded width are saved in browser `localStorage` (`fusion:left-sidebar-collapsed` and `fusion:left-sidebar-width`) and restored on reload. On mobile viewports (`<=768px`), the sidebar is not rendered even when the experiment is enabled. The existing bottom `MobileNavBar` remains the navigation surface. diff --git a/packages/dashboard/app/__tests__/left-sidebar-active-accent.css.test.ts b/packages/dashboard/app/__tests__/left-sidebar-active-accent.css.test.ts new file mode 100644 index 0000000000..5b50794f9c --- /dev/null +++ b/packages/dashboard/app/__tests__/left-sidebar-active-accent.css.test.ts @@ -0,0 +1,38 @@ +import { readFileSync } from "node:fs"; +import path from "node:path"; +import { describe, expect, it } from "vitest"; + +const APP_ROOT = path.resolve(__dirname, ".."); +const LEFT_SIDEBAR_CSS_PATH = path.join(APP_ROOT, "components", "LeftSidebarNav.css"); + +function readLeftSidebarCss(): string { + return readFileSync(LEFT_SIDEBAR_CSS_PATH, "utf8"); +} + +function extractRuleBody(source: string, selector: string): string { + const escapedSelector = selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + const match = source.match(new RegExp(`${escapedSelector}\\s*\\{([\\s\\S]*?)\\}`)); + expect(match, `${selector} rule should exist in LeftSidebarNav.css`).not.toBeNull(); + return match?.[1] ?? ""; +} + +describe("left sidebar active accent CSS", () => { + /** + * FNXC:DashboardStyling 2026-06-21-11:16: + * jsdom cannot resolve custom properties reliably, so the left-sidebar theme-accent invariant is guarded by raw CSS text. The active item and resize handle must reference the universal --accent token and must not regress to workflow todo status tokens. + */ + it("uses the theme accent token for active item and resize handle styling", () => { + const source = readLeftSidebarCss(); + const activeItemBody = extractRuleBody(source, ".left-sidebar-nav__item--active"); + + expect(activeItemBody).toContain("var(--accent)"); + expect(activeItemBody).not.toContain("var(--todo)"); + expect(activeItemBody).not.toContain("var(--todo-bg)"); + expect(activeItemBody).not.toContain("var(--status-todo-bg)"); + + expect(source).toMatch( + /\.left-sidebar-nav__resize-handle:hover::after,\s*\.left-sidebar-nav__resize-handle:focus-visible::after\s*\{[\s\S]*?background:\s*var\(--accent\);[\s\S]*?\}/, + ); + expect(source).not.toContain("--todo"); + }); +}); diff --git a/packages/dashboard/app/components/LeftSidebarNav.css b/packages/dashboard/app/components/LeftSidebarNav.css index 1d5114c0b6..47edd7cd5b 100644 --- a/packages/dashboard/app/components/LeftSidebarNav.css +++ b/packages/dashboard/app/components/LeftSidebarNav.css @@ -87,12 +87,12 @@ The collapse toggle lives in the footer above Settings instead of floating on th } /* -FNXC:DashboardStyling 2026-06-20-20:56: -The active sidebar item must use the defined --status-todo-bg token so the dashboard CSS token-validity gate stays green. FN-6809 replaces the undefined --todo-bg reference without changing the rendered todo status treatment. +FNXC:DashboardStyling 2026-06-21-11:16: +The left sidebar active highlight and resize accent must use the per-theme --accent token so the selected state reflects the active color theme instead of the workflow todo-status blue. FN-6830 keeps this requirement in the base sidebar rules so every theme inherits it without per-theme overrides. */ .left-sidebar-nav__item--active { - background: var(--status-todo-bg); - color: var(--todo); + background: color-mix(in srgb, var(--accent) 15%, transparent); + color: var(--accent); } .left-sidebar-nav__icon-wrap { @@ -161,7 +161,7 @@ The narrower resizable sidebar must preserve row rhythm by truncating labels ins .left-sidebar-nav__resize-handle:hover::after, .left-sidebar-nav__resize-handle:focus-visible::after { - background: var(--todo); + background: var(--accent); } .left-sidebar-nav__resize-handle:focus-visible { diff --git a/packages/dashboard/app/components/WorkflowOptionalStepsPanel.css b/packages/dashboard/app/components/WorkflowOptionalStepsPanel.css index 3b2a8503d6..d458de87a4 100644 --- a/packages/dashboard/app/components/WorkflowOptionalStepsPanel.css +++ b/packages/dashboard/app/components/WorkflowOptionalStepsPanel.css @@ -89,7 +89,7 @@ } .wf-optional-step-remove:hover:not(:disabled) { - color: var(--danger, #ef4444); + color: var(--color-error); } .wf-optional-steps-add { diff --git a/packages/dashboard/app/styles.css b/packages/dashboard/app/styles.css index dda23f1ca6..6f48b9d76c 100644 --- a/packages/dashboard/app/styles.css +++ b/packages/dashboard/app/styles.css @@ -122,6 +122,9 @@ html { --font-mono: "SF Mono", Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* FNXC:DashboardStyling 2026-06-19-05:50: FN-6703 defines the xs font-size token so tokenized mobile mailbox tabs satisfy the dashboard CSS token-validity guard without relying on an undefined fallback. */ --font-size-xs: 0.8rem; + /* FNXC:DashboardStyling 2026-06-21-11:24: Dashboard components must use defined typography tokens so the raw CSS token-validity gate catches real missing custom properties instead of shared type-scale omissions. */ + --font-size-base: 1rem; + --line-height-tight: 1.25; /* Spacing Scale */ --space-xs: 4px;