From c0382c6b97cf87a558f77bdbe3b24b9277c8e5dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ovidiu=20M=C4=83ru=C8=99?= Date: Sat, 6 Jun 2026 05:20:51 +0000 Subject: [PATCH] Keep active workspace controls visible --- apps/web/src/navigator-workspace-cards.css | 4 +- .../web/src/navigator-workspace-cards.test.ts | 43 ++++++++++++++++++- apps/web/src/workspace-card.tsx | 1 + 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/apps/web/src/navigator-workspace-cards.css b/apps/web/src/navigator-workspace-cards.css index fedf1798..9c49d9fc 100644 --- a/apps/web/src/navigator-workspace-cards.css +++ b/apps/web/src/navigator-workspace-cards.css @@ -39,7 +39,9 @@ .workspace-card-wrap:hover .workspace-card-collapse[aria-label^="Add worktree"], .workspace-card-wrap:hover .workspace-card-collapse[aria-controls^="nav-workspace-checkouts-"], .workspace-card-wrap:focus-within .workspace-card-collapse[aria-label^="Add worktree"], -.workspace-card-wrap:focus-within .workspace-card-collapse[aria-controls^="nav-workspace-checkouts-"] { +.workspace-card-wrap:focus-within .workspace-card-collapse[aria-controls^="nav-workspace-checkouts-"], +.workspace-card-wrap.is-active .workspace-card-collapse[aria-label^="Add worktree"], +.workspace-card-wrap.is-active .workspace-card-collapse[aria-controls^="nav-workspace-checkouts-"] { opacity: 1; pointer-events: auto; } diff --git a/apps/web/src/navigator-workspace-cards.test.ts b/apps/web/src/navigator-workspace-cards.test.ts index 8b43199b..ffa86e36 100644 --- a/apps/web/src/navigator-workspace-cards.test.ts +++ b/apps/web/src/navigator-workspace-cards.test.ts @@ -2,7 +2,7 @@ import type { AgentSession, PullRequestSummary, Repo, Workspace, WorktreeCheckout } from "@citadel/contracts"; import { QueryClientProvider } from "@tanstack/react-query"; -import { createElement } from "react"; +import { type ReactNode, createElement } from "react"; import { flushSync } from "react-dom"; import { type Root, createRoot } from "react-dom/client"; import { afterEach, describe, expect, it, vi } from "vitest"; @@ -22,6 +22,7 @@ import { workspaceCheckoutRows, } from "./navigator-workspace-cards.js"; import { ToastProvider } from "./toast.js"; +import { WorkspaceCard } from "./workspace-card.js"; const ts = "2026-06-01T00:00:00.000Z"; const roots: Root[] = []; @@ -255,6 +256,21 @@ describe("navigator workspace checkout cards", () => { expect(prIcon?.getAttribute("title")).toBe("No PR yet"); }); + it("marks active workspace card wrappers so hover-gated controls stay available", () => { + const container = renderWorkspaceCard({ + active: true, + rightControl: createElement( + "button", + { type: "button", className: "workspace-card-collapse", "aria-controls": "nav-workspace-checkouts-ws_1" }, + "Toggle", + ), + }); + + const wrap = container.querySelector(".workspace-card-wrap"); + expect(wrap?.classList.contains("is-active")).toBe(true); + expect(wrap?.querySelector(".workspace-card-collapse")).toBeTruthy(); + }); + it("shows repo name before branch and keeps the stable git worktree name in hover text", () => { const co = checkout("co_api", { name: "api-stable", @@ -532,6 +548,31 @@ function renderCheckoutCard(input: { return rootElement; } +function renderWorkspaceCard(input: { active: boolean; rightControl?: ReactNode }) { + const rootElement = document.createElement("div"); + document.body.appendChild(rootElement); + const root = createRoot(rootElement); + roots.push(root); + flushSync(() => { + root.render( + createElement( + QueryClientProvider, + { client: queryClient }, + createElement(WorkspaceCard, { + workspace: workspace(), + sessions: [], + namespace: null, + namespaces: [], + active: input.active, + onSelect: () => undefined, + rightControl: input.rightControl, + }), + ), + ); + }); + return rootElement; +} + function stateFixture(input: { workspaces: Workspace[]; checkouts?: WorktreeCheckout[] }): StateResponse { return { repos: [], diff --git a/apps/web/src/workspace-card.tsx b/apps/web/src/workspace-card.tsx index a11d18d6..ccb59b99 100644 --- a/apps/web/src/workspace-card.tsx +++ b/apps/web/src/workspace-card.tsx @@ -237,6 +237,7 @@ export function WorkspaceCard( const wrapClassName = [ "workspace-card-wrap", + props.active ? "is-active" : null, props.rightControl ? "has-right-control" : null, reorderIndicator === "above" ? "is-drop-above" : null, reorderIndicator === "below" ? "is-drop-below" : null,