Centralize shared WebUI structural primitives

This commit is contained in:
2026-08-18 13:17:31 +02:00
parent ee5c881df9
commit 7685a103e8
26 changed files with 767 additions and 81 deletions
+15 -12
View File
@@ -13,14 +13,18 @@ domain modules own their compositions.
| 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; `AdminPageLayout` composes the same contract | `PageLayout.tsx`, `page-layout.test.tsx`, Core fallback dashboard, Dashboard module, Ops module, Campaign pages, 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`, Campaign workspace, Campaign module workspace, Templates workspace, Approvals list/detail workspace, and `check-shared-webui-layouts.py` |
| 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 |
| 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 | Reusable responsive grouping around metric cards | 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 | `MetricGrid.tsx`, `MetricCard.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 |
## Boundary
@@ -35,13 +39,12 @@ Raw JSON remains permitted only for diagnostics, expert inspection,
interchange, or conflict evidence. It is not a primary Core configuration
editor.
Raw page-frame and full-canvas workspace debt is registered in the meta
repository and may only decrease. New headed pages use `PageLayout`; pages
inside `WorkspaceLayout` use its `workspace` mode so the pane owns scrolling
while the page retains the standard inset. Module CSS continues to own domain
content layout, never the shared page or workspace frame. Raw toolbar tags,
retired generic grid and description-list classes, raw dialog-form wrappers,
and module-local copies of the shared toolbar/grid/form-section/dialog-anatomy
components 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.
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.