From a9dd2769358d92de5067519a01e409d811b6701f Mon Sep 17 00:00:00 2001
From: iris
Date: Fri, 6 Nov 2026 19:53:31 +0100
Subject: [PATCH] swarm-ui: FieldGrid lays out a row of form fields on one grid
for the forms that each hand-rolled it
Classifier settings, the try-out target row and classification rows, and the
schedule cadence each wrote their own flex row with its own flex basis and
gap. FieldGrid is one grid with equal columns and one gap, FieldGridFull
spans a row, and the four forms use it, so a lone last field keeps its column
width and the columns share their edges in every row.
---
.../swarm-ui/src/pages/ComponentsPage.tsx | 34 +++++++++++++++++++
.../review-settings/ClassifierSettings.css | 16 ++-------
.../review-settings/ClassifierSettings.tsx | 17 +++++-----
.../review-tryout/ClassificationEditor.tsx | 5 +--
.../src/pages/review-tryout/ReviewTryOut.css | 23 +++----------
.../src/pages/review-tryout/ReviewTryOut.tsx | 5 +--
.../src/pages/schedules/ScheduleForm.css | 13 ++-----
.../src/pages/schedules/ScheduleForm.tsx | 5 +--
.../swarm-ui/src/ui/field-grid/FieldGrid.css | 8 +++++
.../swarm-ui/src/ui/field-grid/FieldGrid.tsx | 30 ++++++++++++++++
10 files changed, 99 insertions(+), 57 deletions(-)
create mode 100644 frontend/packages/swarm-ui/src/ui/field-grid/FieldGrid.css
create mode 100644 frontend/packages/swarm-ui/src/ui/field-grid/FieldGrid.tsx
diff --git a/frontend/packages/swarm-ui/src/pages/ComponentsPage.tsx b/frontend/packages/swarm-ui/src/pages/ComponentsPage.tsx
index 3f02ef59..c5024a27 100644
--- a/frontend/packages/swarm-ui/src/pages/ComponentsPage.tsx
+++ b/frontend/packages/swarm-ui/src/pages/ComponentsPage.tsx
@@ -41,6 +41,7 @@ import {
ExpandableCardListSkeleton,
} from "../ui/expandable-card/ExpandableCard.js";
import { ExternalLink } from "../ui/external-link/ExternalLink.js";
+import { FieldGrid, FieldGridFull } from "../ui/field-grid/FieldGrid.js";
import { FormStack } from "../ui/form-stack/FormStack.js";
import { Hint, type HintTone } from "../ui/hint/Hint.js";
import { FormResult } from "../ui/submit/FormResult.js";
@@ -649,6 +650,39 @@ export function ComponentsPage() {
+
+
+
+ {}}
+ />
+ {}}
+ />
+ {}}
+ />
+
+ {}}
+ />
+
+
+
+
+
e.preventDefault()}>
diff --git a/frontend/packages/swarm-ui/src/pages/review-settings/ClassifierSettings.css b/frontend/packages/swarm-ui/src/pages/review-settings/ClassifierSettings.css
index 17f43a36..1d373ce1 100644
--- a/frontend/packages/swarm-ui/src/pages/review-settings/ClassifierSettings.css
+++ b/frontend/packages/swarm-ui/src/pages/review-settings/ClassifierSettings.css
@@ -1,23 +1,11 @@
-/* The settings form: the fields wrap in a row, the provider fields on a row of
- * their own under the ACP runtime, then the save action. */
+/* The settings form: the fields sit on a `FieldGrid`, the provider fields in a
+ * group of their own under the ACP runtime, then the save action. */
.ui-classifier-settings {
display: flex;
flex-direction: column;
gap: 1em;
margin-top: 1em;
}
-/* One grid for every group of fields: each field has the same width and the
- same edges at any width, and a label that wraps cannot push one input lower
- than its neighbour's. */
-.ui-classifier-settings-fields {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(14em, 1fr));
- gap: 0.75em;
-}
-/* A field that needs the whole row (a URL, a model name). */
-.ui-classifier-settings-wide {
- grid-column: 1 / -1;
-}
/* The provider fields, under their own heading. */
.ui-classifier-settings-group {
display: flex;
diff --git a/frontend/packages/swarm-ui/src/pages/review-settings/ClassifierSettings.tsx b/frontend/packages/swarm-ui/src/pages/review-settings/ClassifierSettings.tsx
index cc26bb8f..3ce8bd6a 100644
--- a/frontend/packages/swarm-ui/src/pages/review-settings/ClassifierSettings.tsx
+++ b/frontend/packages/swarm-ui/src/pages/review-settings/ClassifierSettings.tsx
@@ -11,6 +11,7 @@ import { ApiErrorPanel } from "@hive/shared/api-error-panel.js";
import { readApiError, type ProblemDetails } from "@hive/shared/api-error.js";
import { ActionRow } from "../../ui/action-row/ActionRow.js";
import { Button } from "../../ui/button/Button.js";
+import { FieldGrid, FieldGridFull } from "../../ui/field-grid/FieldGrid.js";
import { Hint } from "../../ui/hint/Hint.js";
import { Disclosure } from "../../ui/disclosure/Disclosure.js";
import { SelectField } from "../../ui/select-field/SelectField.js";
@@ -143,7 +144,7 @@ export function ClassifierSettings() {
) : null}
{draft ? (