91 lines
13 KiB
Markdown
91 lines
13 KiB
Markdown
# 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 1–4 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.
|