FN-7972: fix agents controls panel overlapping content
Elevate the Agents controls popover stacking so it layers above agent cards and token usage on desktop and mobile. - Add `.agents-view-primary-actions--controls-open` with z-index 50 when the controls panel is open - Toggle the elevated class from AgentsView when the panel opens - Extend AgentsView tests for open-state class and stacking CSS invariant - Add patch changeset for the operator-facing fix Files changed: .changeset/fn-7972-agents-controls-overlap.md | 7 +++++++ packages/dashboard/app/components/AgentsView.css | 8 ++++++++ packages/dashboard/app/components/AgentsView.tsx | 2 +- .../app/components/__tests__/AgentsView.test.tsx | 17 ++++++++++++----- 4 files changed, 28 insertions(+), 6 deletions(-) Fusion-Task-Id: FN-7972 Fusion-Task-Lineage: e6cca457-1cd1-4577-83a7-d7de7e484580 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-7972-agents-controls-overlap.md
Normal file
7
.changeset/fn-7972-agents-controls-overlap.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
summary: Fix Agents controls panel overlapping surrounding content on narrow viewports.
|
||||
category: fix
|
||||
dev: Elevated the .agent-controls-panel stacking context in AgentsView.css so the open controls popover sits above agent cards and token usage.
|
||||
@@ -101,6 +101,14 @@ The former scoped overrides (.agents-view .view-header padding/border/background
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
/*
|
||||
FNXC:AgentsControlsOverlay 2026-07-15-00:00:
|
||||
FN-7972 requires the open controls panel to layer above agent cards and Token Usage on desktop and mobile. Elevate only its active anchor so unrelated dashboard overlays keep their existing stacking order.
|
||||
*/
|
||||
.agents-view-primary-actions--controls-open {
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
.agent-controls-trigger {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -1401,7 +1401,7 @@ export function AgentsView({ addToast, projectId, onOpenTaskLogs, agentOnboardin
|
||||
<Network size={16} />
|
||||
</button>
|
||||
</div>
|
||||
<div className="agents-view-primary-actions">
|
||||
<div className={`agents-view-primary-actions${isControlsPanelOpen ? " agents-view-primary-actions--controls-open" : ""}`}>
|
||||
<button
|
||||
ref={controlsTriggerRef}
|
||||
className={`btn-icon agent-controls-trigger${isControlsPanelOpen ? " agent-controls-trigger--active" : ""}`}
|
||||
|
||||
@@ -647,13 +647,15 @@ describe("AgentsView", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps New Agent directly accessible on desktop while controls live in popup", async () => {
|
||||
renderView(<AgentsView addToast={mockAddToast} />);
|
||||
it("keeps New Agent directly accessible on desktop while controls live in an elevated popup", async () => {
|
||||
const { container } = renderView(<AgentsView addToast={mockAddToast} />);
|
||||
|
||||
expect(screen.getByRole("button", { name: "New Agent" })).toBeTruthy();
|
||||
expect(screen.queryByRole("dialog", { name: "Agent controls" })).toBeNull();
|
||||
expect(container.querySelector(".agents-view-primary-actions--controls-open")).toBeNull();
|
||||
|
||||
await openControlsPanel();
|
||||
expect(container.querySelector(".agents-view-primary-actions--controls-open")).toBeTruthy();
|
||||
expect(screen.getByLabelText("Filter agents by state")).toBeTruthy();
|
||||
expect(screen.getByLabelText("Show system agents")).toBeTruthy();
|
||||
expect(screen.getAllByRole("button", { name: "Import" }).length).toBeGreaterThan(0);
|
||||
@@ -661,14 +663,15 @@ describe("AgentsView", () => {
|
||||
expect(screen.getByLabelText("Heartbeat speed preset")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("moves import and new-agent actions into the controls popup on mobile", async () => {
|
||||
it("moves import and new-agent actions into an elevated controls popup on mobile", async () => {
|
||||
mockViewportMode.mockReturnValue("mobile");
|
||||
renderView(<AgentsView addToast={mockAddToast} />);
|
||||
const { container } = renderView(<AgentsView addToast={mockAddToast} />);
|
||||
|
||||
expect(screen.queryByRole("button", { name: "Import" })).toBeNull();
|
||||
expect(screen.queryByRole("button", { name: "New Agent" })).toBeNull();
|
||||
|
||||
await openControlsPanel();
|
||||
expect(container.querySelector(".agents-view-primary-actions--controls-open")).toBeTruthy();
|
||||
expect(screen.getByRole("button", { name: "Import" })).toBeTruthy();
|
||||
expect(screen.getByRole("button", { name: "New Agent" })).toBeTruthy();
|
||||
});
|
||||
@@ -1629,10 +1632,14 @@ describe("AgentsView", () => {
|
||||
expect(css).toContain("pointer-events: none");
|
||||
});
|
||||
|
||||
it("keeps a compact mobile Agents label visible, anchors the controls popup to the action row, and expands view toggles to 36px touch targets", () => {
|
||||
it("keeps a compact mobile Agents label visible, elevates the open controls overlay above Agents content, and expands view toggles to 36px touch targets", () => {
|
||||
const css = loadAllAppCss();
|
||||
const mobileCss = css.slice(css.indexOf("@media (max-width: 768px)"));
|
||||
expect(css).toContain(".agents-view-primary-actions {\n position: relative;");
|
||||
expect(css).toContain(".agents-view-primary-actions--controls-open {\n z-index: 50;\n}");
|
||||
expect(css).toContain(".agent-controls-panel {\n position: absolute;\n top: calc(100% + var(--space-sm));\n right: 0;");
|
||||
expect(css).toContain("background: var(--card);");
|
||||
expect(mobileCss).not.toMatch(/\.agents-view-primary-actions--controls-open\s*\{[^}]*z-index:\s*(?:auto|0)/);
|
||||
expect(css).toContain(".agents-view-title h2 {\n display: block;\n font-size: var(--space-lg);");
|
||||
expect(css).toContain(".agent-controls-mobile-actions {");
|
||||
expect(css).toContain(".agent-controls-mobile-actions .btn {");
|
||||
|
||||
Reference in New Issue
Block a user