Table of Contents
- GovOPlaN Interface Pattern Language
- Source Of Truth And Precedence
- Product Contract
- Surface Archetypes
- Placement Grammar
- Visual Grammar
- Wording Grammar
- State Contract
- Consequence And Provenance
- Focused Views
- Accessibility And Responsive Contract
- Component Ownership
- Test Expectations
- Definition Of Done For A Surface
- First Pilot: Campaign
- Revision Procedure
Mirrored from
/mnt/DATA/git/govoplan/docs/INTERFACE_PATTERN_LANGUAGE.md. Origin:repository. Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
GovOPlaN Interface Pattern Language
This document is the cross-repository pattern language for GovOPlaN user interfaces. It turns the existing ethical doctrine, binding UI/UX decisions, layout principles, and module boundary into a common composition and review grammar. It does not replace those sources.
The companion interface surface inventory records which surfaces the current code contributes and where each surface enters the rollout.
Source Of Truth And Precedence
Use the narrowest owning document when changing a rule:
govoplan-core/docs/INTERFACE_ETHICS_AND_DESIGN_DOCTRINE.mdowns why a consequential interface must preserve context, decision, consequence, responsibility, contestability, and traceability.govoplan-core/docs/UI_UX_DECISION_LEDGER.mdowns accepted product decisions such as progressive disclosure, adaptive forms, blocker language, guided operations, and the platform theme contract.docs/FRONTEND_LAYOUT_PRINCIPLES.mdowns the high-level choice between a full-space structured-data workspace and a heading/menu/card workflow or configuration surface.govoplan-core/docs/MODULE_ARCHITECTURE.mdowns the shell, route, navigation, UI-capability, and shared-component boundaries.- This document owns the common pattern names, placement grammar, wording and state conventions, focused-view composition, and definition of done across those sources.
If two rules appear to conflict, do not create a third local convention. Record the conflict in the owning decision ledger, resolve it there, and update the affected patterns and surfaces together.
Product Contract
GovOPlaN should feel calm because it shows what is relevant to the task, not because it hides authority, risk, or evidence. Every surface follows these rules:
- Start with the user's current object and task.
- Show common actions before advanced controls.
- Keep context, status, problems, and the next action spatially connected.
- Make consequential effects explicit before execution and observed effects inspectable afterwards.
- Treat permissions, policy, privacy, and module availability as behavior, not decoration.
- Keep optional modules optional. Compose through core route and UI-capability contracts, never sibling-private components.
- Use the centrally exported core components wherever a matching contract exists. A module-local replacement is not an implementation choice: it is a product exception that requires explicit product-owner authorization.
- Preserve a stable way back to the containing object and the broader system.
- Do not let navigation, selection, or a view switch imply consent.
Surface Archetypes
Choose an archetype from the task, then specialize it for the domain. A route may contain more than one bounded archetype, but it should have one dominant one.
| Archetype | Use when | Standard anatomy | Do not use when |
|---|---|---|---|
| Directory or explorer | Users browse hierarchical collections such as files, mailboxes, calendars, addresses, or records. | Collection/source pane, collection actions, filter in the pane it affects, main list/content pane, optional detail pane. | The content is a set of unrelated settings or workflow stages. |
| List-detail workspace | Users repeatedly find objects, inspect one, and act without losing list context. | Search/filter/list, persistent selected-object context, detail/actions, stable selection and URL. | A single guided operation is the primary task. |
| Focused task view | Only a bounded composition is needed to complete one task. | Task identity and reason, selected object, necessary module regions/actions, progress or status, obvious exit to the full system. | Hiding a surface would obscure a consequence, blocker, or required evidence. |
| Create or edit | Users change one coherent object state. | Adaptive typed form, field-level validation, advanced section, save/cancel, unsaved-change guard. | Discovery-heavy setup or a broad consequential change needs staged review. |
| Guided setup or import | The user must discover, upload, map, test, or preflight before a safe result exists. | Named steps, current progress, preserved inputs, validation/problem list, review, resumable completion where work is durable. | An ordinary edit can be understood as one coherent form. |
| Review or decision | A person must inspect evidence and deliberately approve, reject, send, publish, or otherwise commit. | Decision context, evidence/problems, consequence and reversibility, authority/provenance, explicit action, resulting record. | The interaction is passive inspection. |
| Monitoring, progress, or report | Users observe asynchronous or aggregate state and intervene when needed. | Summary, filters, durable job/item state, last update, retry/reconcile/intervention, detail and evidence. | A toast is sufficient for a short, non-durable local action. |
| Administration or configuration | Users compare and configure separate concerns. | Heading and scope, grouped subnavigation, overview/list plus selected details, adaptive editor or guided risky operation, effective policy and source. | The primary task is browsing one structured object space. |
| Dashboard | Users need a task-oriented starting point across modules. | Prioritized actionable widgets, scoped status, clear destination per widget, explicit refresh/staleness. | It merely duplicates every module navigation item or metric. |
| Public service or entry | An unauthenticated or external participant starts or resumes a service. | Service identity, eligibility/context, privacy and evidence expectations, accessible form/task, save/resume or handoff. | The actor is performing internal administration. |
Placement Grammar
Shell And Navigation
- The global title bar and rail belong to core. A module contributes routes, navigation metadata, and explicit UI capabilities; it does not reproduce the shell.
- Global navigation answers "which service area?" Local subnavigation answers "which stable facet of this object or area?" A progress indicator answers "where am I in this operation?" Do not use those three controls interchangeably.
- Keep the current tenant, actor, object, and selected version or scope stable across local navigation. Guard unsaved work before navigation.
- Permission and capability filtering happens before view composition. A missing menu item is not evidence that an actor lacks backend access, and a visible item is never authorization by itself.
- Route, selection, panel, and view changes must not execute consequential actions.
Page And Workspace
- Structured directories use the full available content space and persistent panes. They do not add a decorative heading row that reduces working height.
- Workflow, configuration, dashboard, and explanatory pages may use a heading. The heading names the task or scoped object and contains only route-level actions.
- Put a collection-wide create action in the heading of the collection it
affects. Use a short, specific label such as
Addwhen the heading already names the object. Do not duplicate that action in a permanently visible side panel. A side panel used as the creation surface appears for creation and is otherwise absent or returns to its documented non-creation purpose. - Put filters beside the list or pane they affect. Put bulk actions immediately above or beside the current selection. Put object actions with the object detail, not in the global title bar.
- Full-page create and edit surfaces put their persistent action cluster in the
upper-right of the page heading.
Discardcomes beforeSave …, with the primary save action at the far right. Keep both controls in the same place across validation, loading, and saved states; guard unsaved work when the user discards or navigates away. Explicit Discard and dirty in-application navigation use the same central unsaved-changes dialog and registered save/discard callbacks. A browser-controlled tab/window unload warning is the only unavoidable different surface. - A page or panel has one visually primary action for its current state. Put secondary actions beside it. Separate destructive actions and name their real effect.
- Dialog actions use a stable footer: cancel/back first, then the primary action at the end. Header and footer stay fixed while long bodies scroll.
- Use cards for independent groups, summaries, and settings blocks. Do not wrap every region in a card or nest cards merely to create spacing.
- When a collapsible card contains one table and no other content, the table uses the card's full available width and body height. The card/table region owns overflow; do not add an inner max-width, decorative wrapper, duplicate padding, or nested scroll container that reduces the working area.
- Row actions in tables are icon-only controls in a stable rightmost action column. Order them by intent: inspect/open, edit, copy/duplicate, transfer/share/download, retry/restore, then remove/delete last. Omit actions only when they are structurally irrelevant to the entire table. An action that belongs to the table but is unavailable for one row remains in its normal position and is disabled; when the reason is not obvious from row state, provide it through the central focusable disabled-action explanation. It does not disappear. Every icon has a translated accessible name and matching tooltip. Separate destructive actions visually, and use a named confirmation/review surface when the consequence cannot be understood from the icon and row context. In an empty editable table, place Add in the same left-most action slot it occupies in a populated row and reserve the remaining slots so the column geometry does not move.
- Transient feedback should not shift the workspace. Durable failures, partial results, and blockers remain attached to the affected item or operation.
Detail And Explanation
- Keep the selected object's identity and material status visible while its detail changes.
- Every non-self-explanatory field uses the central
FieldLabel; short field help sits with that label. A field withoutFieldLabelis an explicit documented omission whose register names the field, rationale, and accessible label source. Users may hide inline help markers with their persisted interface preference; the visible/accessibility label and validation remain. Longer "Why?", policy source, diagnostics, or provenance belongs in an expandable area, detail panel, or review step. - Empty space is not an error. An empty state states what is empty, why that can happen, and the permitted next action. Do not show creation actions to actors who cannot create.
Visual Grammar
- Core owns the appearance contract and shared CSS tokens. Modules use core colors, spacing, radii, shadows, focus treatment, status colors, and disabled treatment; module CSS may specialize layout only.
- Establish hierarchy through spacing, typography, grouping, and placement before adding borders or color.
- Color never carries status or required action alone. Pair it with text and, where useful, an icon.
- Icons support recognition but do not replace accessible names. Use the core icon-name mapping for navigation.
- Keep list columns, tree indentation, headers, dialog dimensions, and action positions stable as content changes.
- Density is a user preference, not a license to remove labels, focus targets, explanations, or consequences.
- Respect system/light/dark themes and reduced-motion preferences through the core contract. Do not build module-local theme systems.
Wording Grammar
Use the same noun for the same domain object in navigation, headings, fields, actions, states, API-facing explanations, and documentation. Prefer the most specific user-facing noun: "Recipients" rather than "Data", "Delivery job" rather than "Process", and "Mail profile" rather than "Configuration" when that is what the user is acting on.
Actions use a verb plus the object or consequence:
- Prefer
Save campaign,Review messages,Queue delivery,Retry failed deliveries, orDelete calendar. - Avoid
Submit,OK,Continue, orExecutewhen a more precise action is available. - Use
Continueonly when it advances a reversible guided flow without committing the final effect. - Do not say
Undowhen the system can only cancel future work, create a correction, supersede a record, or request retraction.
State text describes observed state, not optimism. Use stable shared terms where
they fit: Draft, Ready for review, Blocked, Queued, Running,
Retry scheduled, Partially completed, Completed, Failed, and
Cancelled. Domain-specific states may refine these terms but should not give a
shared term a contradictory meaning.
Blocked and failed actions use the structured language from DUE-005:
- what is unavailable or failed
- why, in plain language
- what must happen next
- who can do it
- where to go
- optional technical details behind deliberate disclosure
Errors should identify the affected object and whether saved state or external effects may already exist. Never expose raw exception text as the only user message.
Use the central dialog, confirmation, alert, and attached-error components for
feedback. window.alert and the global alert function are prohibited. A
genuinely unavoidable exception requires explicit product-owner authorization
and an entry in the Core alert exception register before implementation.
State Contract
Every surface implements the states it can reach; it does not render a blank region while waiting or collapse distinct outcomes into a generic error.
| State | Required treatment |
|---|---|
| Loading | Keep the stable shell and context visible. Name what is loading; preserve usable prior data when safe. |
| Empty | State the scope and reason, then show only permitted next actions. |
| Validation problem | Attach the problem to the field/item and provide a navigable summary when problems span regions or steps. |
| Permission denied | Name the unavailable action or object, the required actor/role where safe, and a valid exit. Do not leak protected data. |
| Capability unavailable | Distinguish not installed, disabled, not configured, unhealthy, and not permitted when the actor may know. Give the responsible actor and target. |
| Offline or unreachable | Preserve local context and unsaved input, show last-known/stale state, and offer a safe retry. Do not present network absence as an authentication failure. |
| Stale or conflicting | Show which data changed, preserve both values where feasible, and offer reload, merge, or explicit overwrite according to policy. |
| Partial result | Show completed and incomplete effects separately. Never label a partial operation successful without qualification. |
| Asynchronous work | Show durable job identity, queued/running/retry/block/final state, last update, progress if meaningful, and leave/return behavior. |
| Success | State the resulting object/effect and provide its evidence or destination. Use a transient toast only when the result is already visible and durable elsewhere. |
| Destructive or corrective action | Preview scope, downstream effects, reversibility limit, evidence, and required confirmation or approval. |
Long-running or external work must expose retry and reconciliation as observable states. The UI must not imply that a request and its external effect were one atomic success when an outbox, worker, or remote system sits between them.
Consequence And Provenance
Before an action affects records, rights, policy, retention, communications, money, external systems, or workflow state, its action surface must answer the decision-surface questions in the interface doctrine. At minimum show:
- affected object and scope
- acting identity or system actor and relevant authority
- immediate and possible downstream effects
- whether the operation is reversible, cancellable, corrective, or final
- blockers and their resolution path
- audit/evidence that will be created
- effective policy or configuration source when it changes the decision
After execution, users must be able to reach the command/job, observed effects, policy result, failures, retries, reconciliation outcome, actor, time, and source data that explain the result. Provenance may be quiet by default, but it must not be absent.
Privacy follows the same rule: lists, previews, logs, notifications, and diagnostics show only the personal or secret data needed for the actor's task. Redaction must be explicit enough that users do not mistake a redacted value for missing source data.
Focused Views
A focused view is a declarative UI composition for a task. It selects the routes, local regions, navigation entries, and actions relevant to that task after installed-module, capability, permission, and policy filtering. It does not change backend authorization or domain state.
A view definition must be able to explain:
- its stable identifier, label, and task purpose
- the current object/scope and default destination
- included navigation and contributed regions/actions, with deterministic order
- the visible escape to the containing module and full system
- why the view is active and how the user may switch when switching is allowed
- what happens to unsaved work when entering, leaving, or switching views
Focused views follow these invariants:
- Do not hide a blocker, material consequence, provenance, or required review merely to make the screen quieter.
- Preserve the global tenant/actor context and provide an obvious exit.
- Filter unavailable contributions without leaving broken separators, empty groups, or dead destinations.
- A manual or automatic switch is navigation, not consent. Guard unsaved work and never execute a domain action as a side effect.
- Display why a non-manual default was selected, for example a role or task default, without exposing protected policy details.
- Treat an unknown or invalid view as a recoverable fallback to the normal module surface.
When more than one source proposes a focused view, use this precedence:
- a manual view pinned for the current user session
- a current-task suggestion, including a future workflow-step suggestion
- the user's saved default
- the role or tenant default
- the normal full interface
Show the active source and an escape to the full interface. A task or workflow suggestion is never an authorization change and never locks the user into the composition; tenant policy may constrain which views are selectable, but it must not hide required evidence or remove that escape. Workflow implementation is explicitly postponed and is not a prerequisite for defining, manually selecting, testing, or piloting focused views. A future workflow module may request a view through a core contract; it must not own the view composition implementation.
Accessibility And Responsive Contract
- Every action is reachable and operable by keyboard in a logical order.
- Use semantic headings, landmarks, labels, tables/lists, and native controls before adding ARIA. Icon-only controls need stable accessible names.
- Focus is visible. Dialogs trap focus, announce their name, and return focus to the control that opened them. Validation moves or links focus to the first relevant problem without losing the problem summary.
- Loading, saved, failed, queued, progress, and externally updated states are announced without repeatedly interrupting the user.
- Disabled primary actions need a focusable explanation; a pointer-only tooltip is insufficient.
- Do not rely on color, hover, drag-and-drop, pointer precision, or animation as the only interaction. Provide keyboard and explicit-control equivalents.
- At narrow widths and high zoom, preserve task order and action access. Collapse secondary panes into an explicit drawer/step and never move a destructive action into the primary position.
- Honor reduced motion. Avoid motion that implies progress when the operation is merely waiting.
- Truncation has an accessible full-value path. Personal or secret values remain redacted according to permission and policy in that path.
Component Ownership
Core already exports shell, navigation, access-boundary, form, dialog, loading,
status, policy/provenance, blocker, review, table, tree, message-display, and
unsaved-change primitives. These centrally exported components are mandatory
across GovOPlaN wherever their contract covers the interaction. In particular,
use the core Card for logical sections, DataGrid for tabular collections and
row actions, and ToggleSwitch (the standard Toggle control) for boolean
settings. Styling a native element or a module-local component to imitate one
of these controls is duplication, not reuse.
A route or domain composition assembled from central primitives is not a custom control. Any new reusable UI control, presentation primitive, or module-local substitute is a custom component and requires explicit product-owner authorization before implementation. Record the authorization in the owning decision or issue together with:
- the narrowly defined purpose and consumers
- why no central component or composition satisfies the need
- the exact scope in which the exception may be used
- its accessibility, state, theme, and test contract
- whether it should remain domain-specific or later become a core component
An authorized custom component serves only that specific purpose. It must not duplicate, fork, restyle into a substitute for, or silently broaden beyond a central component. Code review convenience, an existing local implementation, or a small visual difference is not authorization. When core gains the required contract, migrate the exception unless the product owner explicitly retains it.
Do not promote a component only because two screens look similar. Promote it to
@govoplan/core-webui after a second consumer or a clear platform contract has
proved shared behavior, accessibility, state, and extension needs. Modules own
domain composition, wording, and policy semantics; core owns generic contracts
and appearance.
Scheduling Request Composition Reference
The Scheduling request surface is the first explicit reference composition for these rules:
- The persistent left panel contains
My scheduling requestsandScheduling requests for meas two stacked lists. It preserves list context like mailbox folders but does not invent folders. - The left pane's
Scheduling requestsheading owns one shortAddaction. It opens a new request in the right pane without an extra menu or duplicate launcher. - The right main pane is the stable view/create/edit surface. Selecting a list item opens its details; Add opens the same editor composition used for edit.
Basic information,Calendar integration,Candidate slots, andParticipantsare logical sections rendered with the centralCard.- Privacy and participation behavior is a separate settings
Card; dependent number/password fields are disclosed by their centralToggleSwitch. - Candidate slots and participants are row collections rendered with the
central
DataGrid, including its stable action column. - Calendar integration is a boolean choice rendered with the central
ToggleSwitch; dependent calendar controls are disclosed only when enabled. - Each participant is one structured row containing name, email address, and ordered row actions. An address-parsing text area is not the ordinary editor; parsing pasted address lists belongs only in an explicitly designed bulk import flow.
- View mode shows participation statistics and only state-valid quick actions. Scheduling owns those current domain actions; a future Workflow module may coordinate them through stable action contracts but is not a runtime dependency of the surface.
Apply the underlying placement and component rules to equivalent collection and create/edit surfaces throughout the system; the Scheduling domain names are an example, not a module-local convention.
Test Expectations
For every changed surface, select tests from each applicable layer:
- route and permission tests: module enabled/disabled permutations, route guard, contribution filtering, fallback, and direct-link behavior
- behavior tests: primary task, validation, unsaved-change guard, confirmation, retry/reconcile, partial result, and leave/return behavior
- accessibility tests: semantic names/roles, keyboard order, focus entry/return, live-state announcements, and non-color status meaning
- state tests: loading, empty, denied, capability-missing, stale/conflict, offline, partial, success, and destructive/corrective outcomes as applicable
- composition tests: absent optional module, duplicate/unknown contribution, deterministic ordering, and focused-view fallback
- presentation checks: supported widths/zoom, light/dark/system theme, reduced motion, comfortable/compact density, and long translated text
- i18n checks: user-facing strings owned by the rendering package and structural audits passing
- visual regression: useful for geometry and hierarchy after behavior and accessibility assertions exist; never the only evidence
If the current harness cannot automate a required check, record the gap and the manual evidence in the owning issue. "Not tested" is an inventory state, not a reason to infer that a pattern is satisfied.
Definition Of Done For A Surface
- The dominant task and archetype are recorded in the inventory.
- Placement, action hierarchy, wording, and every reachable state follow this pattern language or an explicit ledger exception.
- Permission, capability, privacy, and redaction behavior are verified.
- Consequence, reversibility, authority, evidence, and provenance are present where applicable.
- Keyboard, focus, announcement, responsive, theme, density, motion, and i18n behavior are covered in proportion to the surface.
- Optional modules remain optional and no sibling-private UI import was added.
- Every matching central component is reused. Any custom-component exception has recorded product-owner authorization, narrow scope, rationale, and tests, and does not duplicate a central component.
- Behavioral/accessibility evidence is linked from the rollout matrix and issue.
- Configured-system help can reach the applicable pattern or reference topic when Docs #15 supplies that experience.
First Pilot: Campaign
Campaign #74 is the first full-domain audit and migration. It should prove patterns before generic extraction:
- #59 and #73: stable, accessible preview and attachment-detail overlays
- #63: review stages, outcomes, blockers, and intervention vocabulary
- #62: explicit synchronous/asynchronous send mode and durable delivery progress
- #65: one coherent report filtering and count-affordance model
- #35: guided first-campaign entry
These slices do not depend on the Workflow runtime. Campaign's current domain-owned review/send state is enough to prove layout, wording, focused-view, progress, intervention, and evidence patterns.
Revision Procedure
- Record a changed product decision in the core UI/UX decision ledger.
- Update the relevant pattern here without copying the full owning doctrine.
- Update the surface inventory and rollout owner/issues.
- Change shared components only where the proven contract belongs to core.
- Migrate and test affected module surfaces.
- Publish configured-system pattern/reference help through the Docs module.