FN-6179: fix tablet nodes overlay stacking

Prevent the NodesView tablet overlay from letting underlying content bleed through.

- make the tablet nodes management overlay fixed, fullscreen, and scrollable with the app background
- add a regression test that asserts the tablet overlay media query and rule properties
- add a patch changeset for the published CLI package bundle

Files changed:
 .changeset/fn-6179-tablet-nodes-overlay.md         |  5 +++++
 packages/dashboard/app/components/NodesView.css    | 12 ++++++++++-
 .../app/components/__tests__/NodesView.test.tsx    | 23 ++++++++++++++++++++--
 3 files changed, 37 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-6179

Fusion-Task-Lineage: 9455b38e-c32f-4865-917a-a06c1cb38840
This commit is contained in:
gsxdsm
2026-06-09 23:52:37 -07:00
parent 9b88c0e307
commit de7b1109e2
3 changed files with 38 additions and 4 deletions

View File

@@ -0,0 +1,5 @@
---
"@runfusion/fusion": patch
---
Fix the Nodes view tablet overlay so node cards and topology content no longer bleed through node detail modals.

View File

@@ -717,6 +717,16 @@
.nodes-view-section-title {
font-size: calc(var(--space-md) + var(--space-xs) / 4);
}
}
/* ── Nodes View Tablet Overlay ───────────────────────────────────────── */
@media (min-width: 769px) and (max-width: 1024px) {
.nodes-management-overlay {
position: fixed;
inset: 0;
z-index: 50;
background: var(--bg);
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
}

View File

@@ -106,9 +106,8 @@ function makeUseNodesResult(overrides: Partial<ReturnType<typeof useNodes>> = {}
};
}
function extractMobileMediaBlocks(css: string): string {
function extractMediaBlocks(css: string, regex: RegExp): string {
const blocks: string[] = [];
const regex = /@media[^{]*\(max-width: 768px\)[^{]*\{/g;
let match: RegExpExecArray | null;
while ((match = regex.exec(css)) !== null) {
@@ -130,6 +129,14 @@ function extractMobileMediaBlocks(css: string): string {
return blocks.join("\n");
}
function extractMobileMediaBlocks(css: string): string {
return extractMediaBlocks(css, /@media[^{]*\(max-width: 768px\)[^{]*\{/g);
}
function extractTabletMediaBlocks(css: string): string {
return extractMediaBlocks(css, /@media[^{]*\(min-width: 769px\)[^{]*\(max-width: 1024px\)[^{]*\{/g);
}
function extractRuleBlock(css: string, selector: string): string {
const escapedSelector = selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const matches = [...css.matchAll(new RegExp(`${escapedSelector}\\s*\\{([^}]*)\\}`, "g"))];
@@ -202,6 +209,18 @@ describe("NodesView", () => {
expect(screen.getByRole("button", { name: "Close nodes view" })).toBeInTheDocument();
});
it("defines nodes overlay as a fixed fullscreen tablet panel", () => {
const tabletCss = extractTabletMediaBlocks(loadAllAppCss());
const overlayRule = extractRuleBlock(tabletCss, ".nodes-management-overlay");
expect(overlayRule).toContain("position: fixed;");
expect(overlayRule).toContain("inset: 0;");
expect(overlayRule).toContain("z-index: 50;");
expect(overlayRule).toContain("background: var(--bg);");
expect(overlayRule).toContain("overflow-y: auto;");
expect(overlayRule).toContain("-webkit-overflow-scrolling: touch;");
});
it("renders docker stat and passes docker data to matching node card", () => {
mockUseNodes.mockReturnValue(makeUseNodesResult({
nodes: [makeNode({ id: "node-1", name: "Alpha", type: "remote", url: "https://alpha.node" })],