feat(FN-787): replace project-switch icon with Building2 for visual distinction

- Replace Folder icon with Building2 in Header project-switch overflow button
- Add Header test for distinct project-switch icon rendering
- Update dashboard README docs for responsive header icon change
This commit is contained in:
gsxdsm
2026-04-03 13:09:34 -07:00
parent c1425b0d8f
commit ec4cf15223
3 changed files with 34 additions and 4 deletions

View File

@@ -55,8 +55,8 @@ AI-guided interactive planning for creating well-specified tasks from high-level
### Responsive Header
The dashboard header adapts across three responsive tiers to remain usable without wrapping or dropping controls:
- **Mobile (≤768px)**: Lower-priority actions (GitHub Import, Planning, Settings, and optionally Usage) move into an accessible overflow menu triggered by a "More actions" button. The menu closes on outside click, Escape key, or after selecting an action. The board search input collapses to an icon button; tapping it expands a focused search field that stays visible while a query is active. The project selector and back button are hidden to save space. View toggle (Board/List), Terminal, Pause, and Stop buttons remain inline for immediate access.
- **Tablet (769px1024px)**: The header uses a compact layout that keeps the view toggle, search input, and both engine controls (Pause/Resume scheduling and Stop/Start AI engine) inline at all times. Lower-priority utility actions (GitHub Import, Planning, Settings, Usage) move into the overflow menu so the engine controls never disappear. The project selector and back button are hidden on tablet.
- **Mobile (≤768px)**: Lower-priority actions (GitHub Import, Planning, Settings, and optionally Usage) move into an accessible overflow menu triggered by a "More actions" button. The menu closes on outside click, Escape key, or after selecting an action. When multiple projects are registered, a dedicated "Switch Project" entry (building icon) appears in the overflow menu, distinct from the folder icon used for file browsing. The board search input collapses to an icon button; tapping it expands a focused search field that stays visible while a query is active. The project selector and back button are hidden to save space. View toggle (Board/List), Terminal, Pause, and Stop buttons remain inline for immediate access.
- **Tablet (769px1024px)**: The header uses a compact layout that keeps the view toggle, search input, and both engine controls (Pause/Resume scheduling and Stop/Start AI engine) inline at all times. Lower-priority utility actions (GitHub Import, Planning, Settings, Usage) move into the overflow menu so the engine controls never disappear. The project selector and back button are hidden on tablet, but the overflow menu includes the same "Switch Project" entry when multiple projects are registered.
- **Desktop (>1024px)**: Full header with all controls and the project selector inline. No overflow menu.
- **Keyboard Accessible**: All controls across tiers expose proper ARIA attributes (aria-expanded, aria-haspopup, aria-label) and support keyboard navigation.

View File

@@ -1,5 +1,5 @@
import { useState, useEffect, useRef, useCallback } from "react";
import { Settings, Pause, Play, Square, LayoutGrid, List, Terminal, Lightbulb, Search, X, Activity, MoreHorizontal, Clock, Folder, History, GitBranch, Workflow, Bot, ChevronLeft, Target } from "lucide-react";
import { Settings, Pause, Play, Square, LayoutGrid, List, Terminal, Lightbulb, Search, X, Activity, MoreHorizontal, Clock, Folder, History, GitBranch, Workflow, Bot, ChevronLeft, Target, Building2 } from "lucide-react";
import type { ProjectInfo } from "../api";
import { ProjectSelector } from "./ProjectSelector";
import { QuickScriptsDropdown } from "./QuickScriptsDropdown";
@@ -490,7 +490,7 @@ export function Header({
role="menuitem"
data-testid="overflow-project-selector-btn"
>
<Folder size={16} />
<Building2 size={16} />
<span>{currentProject ? currentProject.name : "Switch Project"}</span>
</button>
)}

View File

@@ -637,6 +637,36 @@ describe("Header", () => {
expect(onViewAllProjects).toHaveBeenCalledOnce();
});
it("uses distinct icons for project switch and browse files in overflow menu", () => {
const projects = [
{ id: "proj_1", name: "Project One", path: "/path/1", status: "active" as const, isolationMode: "in-process" as const, createdAt: "", updatedAt: "" },
{ id: "proj_2", name: "Project Two", path: "/path/2", status: "active" as const, isolationMode: "in-process" as const, createdAt: "", updatedAt: "" },
];
render(
<Header
projects={projects}
currentProject={projects[0]}
onSelectProject={vi.fn()}
onViewAllProjects={vi.fn()}
onOpenSettings={vi.fn()}
onOpenFiles={vi.fn()}
/>
);
fireEvent.click(screen.getByTitle("More header actions"));
const projectBtn = screen.getByTestId("overflow-project-selector-btn");
const filesBtn = screen.getByTestId("overflow-files-btn");
// The project-switch button should use Building2, not Folder
// Building2 SVG contains a <path> with "M3 21V3h9l1 1h8v17H3Z" or similar building shape
// Folder SVG contains a <path> with "M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" (folder shape)
// Both render SVGs; verify they use different SVG content (different icons)
const projectSvg = projectBtn.querySelector("svg");
const filesSvg = filesBtn.querySelector("svg");
expect(projectSvg).not.toBeNull();
expect(filesSvg).not.toBeNull();
// The two icons should render different SVG paths (not the same icon)
expect(projectSvg!.innerHTML).not.toBe(filesSvg!.innerHTML);
});
it("does not show switch project in overflow menu with single project", () => {
const projects = [
{ id: "proj_1", name: "Project One", path: "/path/1", status: "active" as const, isolationMode: "in-process" as const, createdAt: "", updatedAt: "" },