FN-7881: fix System-controls refresh button mobile layout

Keeps the Command Center System tab's refresh button inline with the section title and pinned to the far right at all breakpoints, instead of dropping below the title on mobile.

- Add a scoped .cc-area-section-header.cc-system-controls-header CSS override (row + space-between) that wins over the shared mobile column-collapse rule for the System tab only
- Add data-testid="cc-system-refresh" to the refresh button for test targeting
- Add regression tests asserting the header stays row-aligned in the DOM and the CSS override is present at the 768px breakpoint
- Add a patch changeset documenting the fix

Files changed:
 .changeset/fn-7881-system-refresh-inline.md        |  7 +++++++
 .../__tests__/SystemControlsArea.test.tsx          | 23 ++++++++++++++++++++++
 .../command-center/areas/SystemControlsArea.css    | 22 +++++++++++++++++++++
 .../command-center/areas/SystemControlsArea.tsx    |  3 ++-
 4 files changed, 54 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-7881

Fusion-Task-Lineage: 80c6fd78-b7e0-4899-b509-b69b8d21e82d

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-12 17:09:15 -07:00
parent c745990aa2
commit b84bd11256
4 changed files with 54 additions and 1 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Keep the System tab refresh button inline with its title and far right on mobile.
category: fix
dev: Scopes a cc-system-controls-header row+space-between override so the shared .cc-area-section-header mobile column collapse no longer pushes the refresh button below the title.

View File

@@ -146,6 +146,29 @@ describe("SystemControlsArea layout integration", () => {
await waitFor(() => expect(mockFetchSystemInfo).toHaveBeenCalled()); await waitFor(() => expect(mockFetchSystemInfo).toHaveBeenCalled());
}); });
it("keeps the System controls refresh button in the scoped inline header", async () => {
render(<CommandCenter projectId="proj-1" />);
fireEvent.click(screen.getByTestId("command-center-tab-system"));
const controls = await screen.findByTestId("cc-system-controls");
const header = controls.querySelector<HTMLElement>(".cc-system-controls-header");
const title = screen.getByRole("heading", { name: "System controls" });
const refresh = screen.getByTestId("cc-system-refresh");
expect(header).toBeInTheDocument();
expect(header).toHaveClass("cc-area-section-header", "cc-system-controls-header");
expect(title.parentElement).toBe(header);
expect(refresh.parentElement).toBe(header);
});
it("keeps the System controls header row override active on mobile", () => {
const css = readFileSync(join(process.cwd(), "app/components/command-center/areas/SystemControlsArea.css"), "utf8");
expect(css).toMatch(/\.cc-area-section-header\.cc-system-controls-header\s*{[^}]*flex-direction:\s*row;[^}]*justify-content:\s*space-between;/s);
expect(css).toMatch(/@media\s*\(max-width:\s*768px\)\s*{[\s\S]*\.cc-area-section-header\.cc-system-controls-header\s*{[^}]*flex-direction:\s*row;[^}]*justify-content:\s*space-between;/);
});
it("keeps the System tab gap and mobile scroll-owner CSS contracts tokenized", () => { it("keeps the System tab gap and mobile scroll-owner CSS contracts tokenized", () => {
const css = readFileSync(join(process.cwd(), "app/components/command-center/CommandCenter.css"), "utf8"); const css = readFileSync(join(process.cwd(), "app/components/command-center/CommandCenter.css"), "utf8");

View File

@@ -7,6 +7,28 @@ log tail use a terminal-style scroll box bounded in height so streaming output
never grows the page; the page must not scroll horizontally (pre wraps). never grows the page; the page must not scroll horizontally (pre wraps).
*/ */
/*
FNXC:SystemPanel 2026-07-12-17:10:
The System-controls refresh button must stay inline with the "System controls"
title and pinned to the far right on every breakpoint. The shared
.cc-area-section-header collapses to a left-aligned column at <=768px (correct
for analytics areas), so scope a row+space-between override to the System tab
only, using a two-class selector so it wins over the shared mobile rule.
*/
.cc-area-section-header.cc-system-controls-header {
flex-direction: row;
align-items: center;
justify-content: space-between;
}
@media (max-width: 768px) {
.cc-area-section-header.cc-system-controls-header {
flex-direction: row;
align-items: center;
justify-content: space-between;
}
}
.cc-syscontrols-grid { .cc-syscontrols-grid {
min-inline-size: 0; min-inline-size: 0;
display: grid; display: grid;

View File

@@ -572,11 +572,12 @@ export function SystemControlsArea({ projectId, addToast }: SystemControlsAreaPr
return ( return (
<> <>
<div className="cc-area-section" data-testid="cc-system-controls"> <div className="cc-area-section" data-testid="cc-system-controls">
<div className="cc-area-section-header"> <div className="cc-area-section-header cc-system-controls-header">
<h3 className="cc-area-section-title">{t("systemControls.title", "System controls")}</h3> <h3 className="cc-area-section-title">{t("systemControls.title", "System controls")}</h3>
<button <button
type="button" type="button"
className="btn-icon" className="btn-icon"
data-testid="cc-system-refresh"
onClick={() => void loadInfo()} onClick={() => void loadInfo()}
title={t("systemControls.refresh", "Refresh capabilities")} title={t("systemControls.refresh", "Refresh capabilities")}
aria-label={t("systemControls.refresh", "Refresh capabilities")} aria-label={t("systemControls.refresh", "Refresh capabilities")}