FN-8751: add depth to expanded sidebar

Give the expanded desktop sidebar a floating visual layer above board content.

- Elevate the expanded sidebar with tokenized shadow and stacking context.
- Keep collapsed and mobile navigation visually flat.
- Cover the depth behavior with CSS-focused component tests.

Files changed:
 .../dashboard/app/components/LeftSidebarNav.css    |  6 +++++
 .../components/__tests__/LeftSidebarNav.test.tsx   | 26 +++++++++++++++++++---
 2 files changed, 29 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-8751

Fusion-Task-Lineage: 2c3197dc-f4f4-4d48-81bb-3fab67310e60

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-08-02 22:47:04 -07:00
parent 34ed2d1ffb
commit 27d5bbc80e
2 changed files with 29 additions and 3 deletions

View File

@@ -4,11 +4,15 @@ The experimental sidebar is a persistent desktop/tablet navigation replacement f
FNXC:Navigation 2026-06-22-18:00:
The border between left sidebar and main content should be invisible while the sidebar remains draggable. Keep the resize handle's invisible hit target and hover/focus accent, but remove the persistent vertical rule and footer divider so the shell reads as one continuous surface.
FNXC:Navigation 2026-08-03-05:34:
Expanded desktop/tablet navigation needs the same tokenized floating depth as the unpinned right dock so board cards paint beneath its outer edge. Keep the shell above adjacent content without changing its flex sizing or resize hit target; rail mode explicitly removes the shadow and stays flat.
*/
.left-sidebar-nav {
--left-sidebar-nav-width: calc(var(--space-2xl) * 7);
--left-sidebar-nav-rail-width: calc(var(--space-2xl) * 2);
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
box-sizing: border-box;
@@ -17,6 +21,7 @@ The border between left sidebar and main content should be invisible while the s
min-height: 0;
background: var(--surface);
color: var(--text);
box-shadow: var(--shadow-lg);
font-family: var(--font-primary);
}
@@ -273,6 +278,7 @@ The footer has no top divider; it remains a functional footer cluster but should
.left-sidebar-nav--collapsed {
width: var(--left-sidebar-nav-rail-width);
min-width: var(--left-sidebar-nav-rail-width);
box-shadow: none;
}
.left-sidebar-nav--collapsed .left-sidebar-nav__label,

View File

@@ -1,11 +1,10 @@
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { fireEvent, render, screen, within } from "@testing-library/react";
import type { ComponentProps } from "react";
import { LeftSidebarNav } from "../LeftSidebarNav";
import type { PluginDashboardViewEntry, ProjectInfo } from "../../api";
import type { TaskView } from "../../hooks/useViewState";
import { loadComponentCss } from "../../test/cssFixture";
const projects: ProjectInfo[] = [
{
@@ -28,7 +27,7 @@ const projects: ProjectInfo[] = [
},
];
const leftSidebarNavCss = readFileSync(resolve(__dirname, "../LeftSidebarNav.css"), "utf8");
const leftSidebarNavCss = loadComponentCss("LeftSidebarNav.css");
const obsoleteCollapseToggleFloatingClass = "left-sidebar-nav__collapse-toggle--" + "floating";
const newTaskSurfaceEnumeration = [
"[x] Components that render the affordance: Grep confirms LeftSidebarNav is the only persistent sidebar renderer and App.tsx mounts it once.",
@@ -544,6 +543,27 @@ describe("LeftSidebarNav", () => {
expect(within(sidebar).getAllByRole("button").at(-1)).toBe(screen.getByTestId("sidebar-nav-settings"));
});
it("keeps expanded depth above board content while collapsed and mobile navigation remain flat", () => {
const { unmount } = renderSidebar();
const expandedSidebar = screen.getByTestId("left-sidebar-nav");
const expandedRule = getCssRuleBlock(leftSidebarNavCss, ".left-sidebar-nav");
const collapsedRule = getCssRuleBlock(leftSidebarNavCss, ".left-sidebar-nav--collapsed");
expect(expandedSidebar).not.toHaveClass("left-sidebar-nav--collapsed");
expect(expandedRule).toContain("position: relative");
expect(expandedRule).toContain("z-index: 1");
expect(expandedRule).toContain("box-shadow: var(--shadow-lg)");
expect(expandedRule).not.toMatch(/\d+px|#|rgb\(/i);
unmount();
window.localStorage.setItem("fusion:left-sidebar-collapsed", "true");
renderSidebar();
expect(screen.getByTestId("left-sidebar-nav")).toHaveClass("left-sidebar-nav--collapsed");
expect(collapsedRule).toContain("box-shadow: none");
expect(leftSidebarNavCss).toMatch(/@media \(max-width: 768px\)\s*\{\s*\.left-sidebar-nav\s*\{\s*display:\s*none;/);
expect(leftSidebarNavCss).toMatch(/html\[data-viewport-mode="mobile"\] \.left-sidebar-nav\s*\{\s*display:\s*none;/);
});
it("keeps collapse toggle styling tokenized and removes the floating modifier", () => {
expect(leftSidebarNavCss).not.toContain(obsoleteCollapseToggleFloatingClass);