From abf35d75f32de28e15f7a063f73cc41e5f29bbb2 Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Tue, 18 Aug 2026 10:42:52 +0200 Subject: [PATCH] Adopt shared WebUI layout primitives --- docs/INTERFACE_PATTERN_MIGRATION.md | 7 ++++-- src/govoplan_forms/backend/manifest.py | 3 ++- .../features/forms/FormDefinitionDialog.tsx | 22 +++++++++--------- webui/src/features/forms/FormsPage.tsx | 6 ++--- webui/src/styles/forms.css | 23 ++----------------- 5 files changed, 23 insertions(+), 38 deletions(-) diff --git a/docs/INTERFACE_PATTERN_MIGRATION.md b/docs/INTERFACE_PATTERN_MIGRATION.md index 25e35d6..895bd0a 100644 --- a/docs/INTERFACE_PATTERN_MIGRATION.md +++ b/docs/INTERFACE_PATTERN_MIGRATION.md @@ -29,5 +29,8 @@ submissions, receipts, and handoff execution. The module uses shared controls, dialogs, blockers, field help, statuses, loading, empty/error states, disabled reasons, confirmations, and unsaved-draft -guards. Existing responsive list/editor layouts remain bounded. English and -German catalogues cover the owned route and editor vocabulary. +guards. The catalogue action row now uses the shared responsive +`ActionToolbar`; equal-column definition/editor groups use `FormGrid` and its +named narrow-layout collapse policy. These layout contracts do not change +filter scope, permissions, revision semantics, or publication consequences. +English and German catalogues cover the owned route and editor vocabulary. diff --git a/src/govoplan_forms/backend/manifest.py b/src/govoplan_forms/backend/manifest.py index 95da738..1890f92 100644 --- a/src/govoplan_forms/backend/manifest.py +++ b/src/govoplan_forms/backend/manifest.py @@ -194,7 +194,8 @@ manifest = ModuleManifest( summary="Create immutable, versioned schemas consumed by Forms Runtime and institutional services.", body=( "Each revision fixes field types, options, constraints, draft, attachment, signature, policy, and handoff requirements. " - "Publishing is explicit; existing submissions continue to retain their exact revision." + "Publishing is explicit; existing submissions continue to retain their exact revision. The catalogue action row and " + "definition field groups reflow at narrow widths without changing filter scope, permissions, or lifecycle effects." ), layer="configured", documentation_types=("admin", "user"), diff --git a/webui/src/features/forms/FormDefinitionDialog.tsx b/webui/src/features/forms/FormDefinitionDialog.tsx index 2b48c5f..1106e8b 100644 --- a/webui/src/features/forms/FormDefinitionDialog.tsx +++ b/webui/src/features/forms/FormDefinitionDialog.tsx @@ -1,6 +1,6 @@ import { ArrowDown, ArrowUp, Eye, Languages, Plus, Trash2 } from "lucide-react"; import { useEffect, useMemo, useState } from "react"; -import { +import { FormGrid, Button, ConfirmDialog, Dialog, @@ -198,7 +198,7 @@ export default function FormDefinitionDialog({
{error && {error}} -
+ setDraft({ ...draft, title: event.target.value })} /> @@ -260,7 +260,7 @@ export default function FormDefinitionDialog({ placeholder="Optional instructions announced before the Form" /> -
+

Fields

@@ -333,19 +333,19 @@ export default function FormDefinitionDialog({ function ConstraintFields({ field, disabled, onChange }: { field: FormFieldDefinition; disabled: boolean; onChange: (value: Record) => void }) { if (["text", "multiline_text", "email"].includes(field.value_type)) { return ( -
+ onChange(patchConstraint(field.constraints, "min_length", event.target.value))} /> onChange(patchConstraint(field.constraints, "max_length", event.target.value))} /> onChange(patchTextConstraint(field.constraints, "pattern", event.target.value))} /> -
+ ); } if (["integer", "number"].includes(field.value_type)) { return ( -
+ onChange(patchConstraint(field.constraints, "minimum", event.target.value))} /> onChange(patchConstraint(field.constraints, "maximum", event.target.value))} /> -
+ ); } return null; @@ -367,7 +367,7 @@ function ConditionFields({ const predicate = condition?.kind === "predicate" ? condition : null; const candidates = fields.filter((item) => item.key !== currentKey && item.key.trim()); return ( -
+ setQuery(event.target.value)} placeholder="Search definitions" aria-label="Search Form definitions" /> @@ -166,7 +166,7 @@ export default function FormsPage({ settings, auth }: PlatformRouteContext) { {total} -
+ {error && {error}} {!canWrite && } diff --git a/webui/src/styles/forms.css b/webui/src/styles/forms.css index 5a69d35..c89502d 100644 --- a/webui/src/styles/forms.css +++ b/webui/src/styles/forms.css @@ -145,12 +145,6 @@ justify-content: flex-end; } -.form-definition-grid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 12px 16px; -} - .form-definition-wide { grid-column: 1 / -1; } @@ -229,13 +223,6 @@ grid-column: 2 / -1; } -.form-field-constraints, -.form-field-condition { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 9px; -} - .form-composition-section { display: flex; flex-direction: column; @@ -302,9 +289,7 @@ } .form-preview-grid { - display: grid; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 18px; + min-width: 0; } .form-preview-grid > div { @@ -374,14 +359,10 @@ } @media (max-width: 620px) { - .form-definition-grid, - .form-field-constraints, - .form-field-condition, .form-page-editor-heading, .form-section-editor, .form-localization-editor, - .form-localization-fields, - .form-preview-grid { + .form-localization-fields { grid-template-columns: 1fr; }