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
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
@@ -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 {
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
}
|
||||
|
||||
.wf-optional-step-remove:hover:not(:disabled) {
|
||||
color: var(--danger, #ef4444);
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
.wf-optional-steps-add {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user