Files
govoplan-core/docs/INTERFACE_PATTERN_MIGRATION.md
T

13 KiB
Raw Blame History

Core Interface Pattern Migration

This document records the Core-owned part of the product-wide interface pattern-language rollout. The normative product grammar and complete route inventory live in the govoplan meta repository. Core owns reusable behavior; domain modules own their compositions.

Core Surfaces

Surface Pattern Consequence and provenance contract Evidence
User settings Two-zone settings workspace with typed controls and unsaved-change protection Save actions distinguish busy, unchanged, and test-in-progress states; contextual help resolves through Docs or the hosted fallback SettingsPage.tsx, test-core-interface-patterns.mjs
Reusable credentials Repeated administration with an adaptive create/edit dialog, optional password generator, and destructive confirmation Secret values are write-only; generated candidates use the browser cryptographic API without a weak fallback and do not replace the field until explicitly confirmed; scope/permission blockers name the required action, responsible actor, and destination; unavailable row actions remain keyboard-explainable CredentialEnvelopeManager.tsx, shared PasswordField, PasswordGeneratorDialog, ActionBlockerHint, Button, TableActionGroup, and ConfirmDialog
Retention policy Effective-policy editor with inherited source paths and typed, narrowing-only controls Parent locks and missing write authority are explicit; the save action distinguishes locks, missing target, loading, clean draft, and active save RetentionPolicyManagement.tsx, policy logic tests, test-core-interface-patterns.mjs
Module lifecycle Guided operator projection over durable installer-queue evidence Preflight, handoff, progress, stale evidence, recovery, and rollback consequences remain visible Admin module lifecycle tests and the Core installer-queue contract
Shared page frame Domain-neutral headed page layout used by Core and optional modules Standalone, workspace, and embedded modes make inset and scroll ownership explicit; sticky heading, rich descriptions, route actions, notices, loading, narrow-layout collapse, and contextual-help identity are centralized; composite administration workspaces may delegate the visible heading to their contributed panel while retaining the same frame; AdminPageLayout composes the contract PageLayout.tsx, page-layout.test.tsx, Core Settings, Access administration, Docs, Mail bounce processing, Dashboard, Ops, Campaign, and check-shared-webui-layouts.py
Full-canvas workspace Navigation/content and list/detail canvases that own pane geometry and scrolling Navigation and split variants, primary-pane width, pane-owned or contained scrolling, responsive stacking or navigation collapse, pane labels, and contextual-help identity are centralized without encoding domain navigation WorkspaceLayout.tsx, workspace-layout.test.tsx, Core Settings, Access administration, Docs, Organizations, Campaign, Templates, Approvals, and check-shared-webui-layouts.py; the raw-workspace exception baseline is empty
Full-height module frame Outer module landmark and viewport/container sizing WorkspaceFrame centralizes surface, overflow, box sizing, accessible naming, help identity, and application-viewport height so modules do not copy the 100vh - shell frame WorkspaceFrame.tsx, layout-primitives.test.tsx, Dataflow, Workflow, Datasources, Distribution Lists, Notifications, Tasks, Scheduling, Forms, Portal, Projects, Records, and Reporting
Responsive action toolbar Domain-neutral action and filter grouping for pages, workspaces, editors, and overlays Density, surface, grouping, flexible space, accessible naming, toolbar help identity, and responsive wrapping are centralized while modules retain action wording, authority, and consequence ActionToolbar.tsx, layout-primitives.test.tsx, WYSIWYG, Calendar, Files, Forms, Templates, and the product-wide primitive check
Semantic page and pane action bars Overview, collection, detail, editor, and workspace intent declared independently from frame geometry; full-canvas panes add workspace/collection/detail/editor scope Core renders guarded Reload in the right-aligned group immediately before Create/primary actions; editor persistence owns clean, dirty, invalid, saving, failed, and conflict feedback plus guarded Discard and far-right Save; destructive actions occupy an explicit named boundary; read-only surfaces do not invent Save PageActionBar.tsx, WorkspaceActionBar.tsx, PAGE_LAYOUT_USAGE_GUIDELINES.md, component and browser conformance, every headed page and full-canvas workspace, and the discovery-based check-shared-webui-layouts.py
Catalogue and state composition Search/filter bars, selectable navigation lists, count badges, and empty/blocked/error panels Width, surface, wrap, selection geometry, title/description truncation, numeric emphasis, state sizing, tone and action placement are centralized; modules retain query behavior, object state and consequences FilterBar.tsx, SelectionList.tsx, CountBadge.tsx, StatePanel.tsx, layout-primitives.test.tsx, and list/detail modules across Cases, Committee, Dataflow, Forms, Notifications, Portal, Postbox, Projects, Records, Reporting, Tasks, Templates, and Workflow
Content and form grids Equal-column content, field, and native-form geometry Explicit 14 columns, standard gaps, item spans, alignment, and named narrow/workspace/standard/wide collapse points replace generic and module-prefixed copies; unequal domain tracks remain local ContentGrid.tsx, layout-primitives.test.tsx, Core dashboard/settings/mail, Calendar dialogs, Forms editor, Datasources, Postbox, Campaign, administration surfaces, and the product-wide primitive check
Content sections Repeated editor/detail section surfaces Border, surface, compact/default density, stacked flow and block rhythm are centralized without encoding section contents ContentSection.tsx, layout-primitives.test.tsx, Datasources, Distribution Lists, Templates, Dataflow, and Workflow
Form sections Reusable heading/description/action/content grouping inside forms Plain, separated, and panel variants centralize hierarchy and narrow action placement without moving validation, permissions, values, or domain wording into Core FormSection.tsx, layout-primitives.test.tsx, Addresses contact editing, and Quick Access preferences
Metric groups and drill-downs Reusable responsive grouping around metric cards with an explicit optional detail affordance Fixed one-to-five and auto-fit columns, minimum card widths, density, block/inset/zero spacing, and named collapse points replace the product-wide metric-grid class and cross-module dashboard overrides; typed link or in-page drill-downs name their destination while summary-only, non-enumerable, derived, or privacy-suppressed values remain inert MetricGrid.tsx, MetricCard.tsx, metric-card.test.tsx, layout-primitives.test.tsx, Core and Dashboard summaries, administration, Campaign, Ops, Files, Search, and dashboard widgets
Description lists Semantic property and fact presentation Stacked and inline variants, one-to-five list columns, density, term width, wrapping, and responsive collapse replace both admin-details-grid and detail-list; DescriptionItem preserves native dt/dd anatomy DescriptionList.tsx, layout-primitives.test.tsx, Access and Tenancy administration, Audit, Policy, Campaign reports/imports, Docs, Settings, Ops, and Reporting
Dialog anatomy Shared outer dialog plus composable body and footer regions Size and administration variants, body padding, descriptions, notices, fixed action wrapping, native form flow, and section grouping are centralized; focus trapping and stack lifecycle remain unchanged Dialog.tsx, DialogAnatomy.tsx, dialog-focus.test.tsx, layout-primitives.test.tsx, Addresses, Calendar, Records, Datasources, Distribution Lists, Files, and Templates
Definition-editor visuals Reusable graph palette, canvas chrome, node icon/port geometry, empty overlay and floating activity state Core owns visual and responsive anatomy while node/edge types, validation, execution, provenance and workflow semantics remain in Dataflow or Workflow DefinitionPalette.tsx, DefinitionNodeIcon.tsx, FloatingStatus.tsx, shared definition styles, Dataflow and Workflow structure/build checks
Shared configuration primitives Cross-module component contract Dialog focus, blocker structure, disabled-action focus, route/page/field/action F1 help, unsaved changes, confirmation, loading, alerts, problem lists, and policy provenance are centralized Core component tests, CONTEXTUAL_HELP_CONTRACT.md, and module-permutation build
Measured operation feedback LoadingFrame over existing content Use indicator="none" with native measured progress for long-running operations; progress={null} means unknown, never a synthetic percentage. Keep dialog content inert and close controls disabled until success or error. Existing consumers retain their loading indicator. Files archive inspection/extraction, layout primitive tests, managed-archive browser conformance

Boundary

Side-rail customization uses the shared NavigationPreferenceEditor for system, tenant, personal, and View layouts. Modules and labelled separators share one ordered list, with pointer drag-and-drop, keyboard reordering, and explicit add/remove actions. Consumers retain persistence and dirty-state ownership; mounting the editor does not create a draft change. See NAVIGATION_LAYOUT_CONTRACT.md for inheritance, locked items, optional-module preservation, and collapsed-rail grouping.

Action columns use TableActionGroup or declare columnType: "actions" when their composition differs. DataGrid owns measured action minima, initial column allocation, persistent resizing, and local horizontal scrolling; consumers must not compensate with clipped overflow or copied fixed widths. See DATAGRID_SIZING_CONTRACT.md. Dialog forms use DialogForm and FormGrid inside the shared size-bounded dialog. Do not add a content minimum wider than the panel's padded interior. Genuinely wide content, such as a table, owns its own local scroller instead of making the entire dialog scroll horizontally.

In FormGrid and FormLayout, direct FormField and ToggleSwitch items align their controls at the row's lower edge. A single control inside a GridItem follows the same rule. Labels may wrap without shifting adjacent switches up into the label row. Do not add per-module top margins or empty labels; single-column layouts must not retain a phantom label spacer.

Credential editors resolve public reference labels when opened. A failed save displays its error inside the dialog and keeps the entered draft for an explicit retry. While a write is pending, repeated submission, edits, and dialog dismissal are disabled; no configured secret is read back from storage.

The shared rich-text editor emits content changes only for actual document edits. Mounting, read-only changes, loading a saved value, and switching between visual and source inspection must preserve the controlled HTML without marking the owning page dirty. This is especially important for legacy Campaign HTML: merely visiting Template must not normalize it or require a save on leaving. The WYSIWYG lifecycle browser conformance covers both visual and legacy-source initial content, as well as genuine typing.

Files and Mail are the first two external consumers of the layered server/credential/policy pattern. Their own repositories retain provider discovery, transport behavior, authorization, and migration evidence. Remaining module surfaces are tracked by bounded module-owned issues under GovOPlaN #11; they are not reasons to add sibling-private behavior to Core.

Raw JSON remains permitted only for diagnostics, expert inspection, interchange, or conflict evidence. It is not a primary Core configuration editor.

New headed pages use PageLayout; full-canvas modules use WorkspaceFrame and, where applicable, WorkspaceLayout, so Core owns the frame and pane scrolling. Module CSS continues to own unequal domain content layout, never the shared page, workspace, toolbar, state, list, filter, metric, section, or graph chrome. Retired copies and module-local component definitions are rejected by check-shared-webui-primitives.py. That check also requires standard dialog widths to use Dialog size and keeps every remaining domain-specific width in a reviewed, decrease-only exception baseline. The companion layout check now has zero raw page-frame and zero raw workspace exceptions, discovers semantic consumers without a hand-maintained route list, requires semantic action bars on WorkspaceFrame routes, and rejects ad-hoc panel-header toolbars.