FN-6985: pack embedded automations panes
Keep the embedded Automations pane list and detail content top-packed instead of spreading vertically. - Add grid row and alignment rules so narrow embedded Automations content stays content-sized.\n- Cover populated embedded list/detail rendering and CSS contracts for mobile and wide layouts.\n- Add a patch changeset for the published Fusion package.\n\nFiles changed:\n .changeset/fn-6985-automations-spacing.md | 7 +++\n packages/dashboard/app/components/ScriptsModal.css | 14 +++++-\n .../__tests__/ScheduledTasksModal.test.tsx | 52 ++++++++++++++++++++++\n 3 files changed, 72 insertions(+), 1 deletion(-) Fusion-Task-Id: FN-6985 Fusion-Task-Lineage: ba2b117a-4dc5-4bc9-9ecb-7bc008cd79cd
This commit is contained in:
7
.changeset/fn-6985-automations-spacing.md
Normal file
7
.changeset/fn-6985-automations-spacing.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
summary: Fix excessive spacing in the embedded Automations pane.
|
||||
category: fix
|
||||
dev: Top-pack embedded Automations grid rows and add regression coverage for the list/detail layout.
|
||||
@@ -1278,15 +1278,27 @@ With the header now edge-to-edge and dividerless, the first body row still needs
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
/* Two-pane body: single column by default (narrow); two columns when the container is wide enough. */
|
||||
/*
|
||||
FNXC:Automations 2026-06-24-23:30:
|
||||
The embedded single-column Automations list/detail grid must not stretch implicit rows to fill the pane; stretch pushes the selected detail card far below the list row on tall/narrow surfaces. Keep rows content-sized and top-aligned so toolbar, list, and detail stay packed while the wide breakpoint only changes the column template.
|
||||
*/
|
||||
.automations-two-pane {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-auto-rows: max-content;
|
||||
align-content: start;
|
||||
align-items: start;
|
||||
gap: var(--space-lg);
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.automations-two-pane {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.automations-single-pane {
|
||||
min-height: 0;
|
||||
flex: 1;
|
||||
|
||||
@@ -392,6 +392,58 @@ describe("ScheduledTasksModal", () => {
|
||||
expect(screen.queryByRole("button", { name: "Close" })).toBeNull();
|
||||
});
|
||||
|
||||
it("packs populated list and selected detail panes in the embedded list/detail structure", async () => {
|
||||
mockFetchRoutines.mockResolvedValue([
|
||||
makeRoutine({ id: "routine-backup", name: "Database Backup", command: "fn backup --create" }),
|
||||
makeRoutine({ id: "routine-disabled", name: "Disabled Import", command: "fn import", enabled: false }),
|
||||
]);
|
||||
|
||||
const { container } = render(
|
||||
<ScheduledTasksModal onClose={onClose} addToast={addToast} presentation="embedded" />,
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole("option", { name: /database backup/i })).toBeDefined();
|
||||
});
|
||||
|
||||
const twoPane = container.querySelector(".automations-two-pane");
|
||||
const listPane = container.querySelector(".automations-list-pane");
|
||||
const detailPane = container.querySelector(".automations-detail-pane");
|
||||
expect(twoPane).not.toBeNull();
|
||||
expect(listPane).not.toBeNull();
|
||||
expect(detailPane).not.toBeNull();
|
||||
expect(twoPane?.children[0]).toBe(listPane);
|
||||
expect(twoPane?.children[1]).toBe(detailPane);
|
||||
expect(screen.getByText("Select an automation")).toBeDefined();
|
||||
expect(screen.getByText("Disabled")).toBeDefined();
|
||||
|
||||
fireEvent.click(screen.getByRole("option", { name: /database backup/i }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(detailPane?.querySelector(".routine-card .routine-card-name")?.textContent).toBe("Database Backup");
|
||||
});
|
||||
expect(screen.getByText("fn backup --create")).toBeDefined();
|
||||
expect(container.querySelector(".automations-single-pane")).toBeNull();
|
||||
});
|
||||
|
||||
it("keeps embedded automation grid rows top-packed while preserving wide two-pane rules", () => {
|
||||
const source = readFileSync(resolve(__dirname, "../ScriptsModal.css"), "utf8");
|
||||
const baseRule = source.match(/\.automations-two-pane\s*\{[^}]*\}/)?.[0] ?? "";
|
||||
const containerRule = source.match(/@container \(min-width: 900px\)\s*\{\s*\.automations-two-pane\s*\{[^}]*\}/)?.[0] ?? "";
|
||||
const mediaRule = source.match(/@media \(min-width: 900px\)\s*\{\s*\.automations-two-pane\s*\{[^}]*\}/)?.[0] ?? "";
|
||||
const mobileRule = source.match(/@media \(max-width: 768px\)\s*\{[\s\S]*?\.automations-two-pane\s*\{[^}]*\}/)?.[0] ?? "";
|
||||
|
||||
expect(baseRule).toContain("grid-template-columns: 1fr;");
|
||||
expect(baseRule).toContain("align-content: start;");
|
||||
expect(baseRule).toContain("align-items: start;");
|
||||
expect(baseRule).toContain("grid-auto-rows: max-content;");
|
||||
expect(containerRule).toContain("grid-template-columns: minmax(0, 18rem) minmax(0, 1fr);");
|
||||
expect(containerRule).toContain("align-items: start;");
|
||||
expect(mediaRule).toContain("grid-template-columns: minmax(0, 18rem) minmax(0, 1fr);");
|
||||
expect(mediaRule).toContain("align-items: start;");
|
||||
expect(mobileRule).toContain("grid-template-columns: 1fr;");
|
||||
});
|
||||
|
||||
it("does not dismiss on Escape in embedded mode", async () => {
|
||||
render(<ScheduledTasksModal onClose={onClose} addToast={addToast} presentation="embedded" />);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user