27 KiB
GovOPlaN UI/UX Decision Ledger
This ledger records product UI/UX decisions that affect admin, settings, configuration, connector, policy, and module-management surfaces. It is a binding design reference: future implementation should follow these decisions unless the decision is explicitly revised here and affected screens are updated to match.
Active tracking issue: add-ideas/govoplan-core#225.
Operating Rule
GovOPlaN must expose advanced platform capability without presenting the user with every option at once. Non-technical users should be able to complete common workflows through guided, plain-language flows. Expert and diagnostic detail may exist, but it must be deliberately layered.
The ethical design doctrine in INTERFACE_ETHICS_AND_DESIGN_DOCTRINE.md is the
normative baseline for this ledger. A screen can be visually quiet and still be
ethically complete only when it preserves context, consequence,
contestability, responsibility, and traceability at the point of action.
Binding Decisions
| ID | Decision | Status | Applies To |
|---|---|---|---|
| UX-001 | Use progressive disclosure by default. Common decisions stay visible; advanced or hazardous options live in collapsed panels, later wizard steps, or explicit advanced sections. | Accepted | Admin, settings, connector setup, policy editors, module operations |
| UX-002 | Raw JSON is not a primary configuration editor. Every normal configuration path needs typed controls, validation, and help text. JSON may be shown for import/export, diagnostics, or expert inspection only. | Accepted | All admin/configuration UIs |
| UX-003 | Prefer guided workflows over option dumps for setup and risky changes. Use wizards for connector setup, configuration package import, module install/uninstall, destructive actions, and policy changes with broad impact. | Accepted | Connectors, package import, module lifecycle, governance/policy |
| UX-004 | Discover technical values when possible. Ask for the smallest user-known input, then discover and prefill technical fields for review. | Accepted | File connectors, mail/groupware, public URLs, future external providers |
| UX-005 | Disabled actions and failed steps must explain why they are unavailable, who can fix them, and where to go next. Silent disabled states are not acceptable for primary actions. | Accepted | All primary actions |
| UX-006 | Explanations must be available but quiet. Use short inline text and expose richer explanations through help affordances, side panels, expandable sections, or review steps. | Accepted | All complex forms and flows |
| UX-007 | Creation/editing should prefer modals or focused step flows when it reduces page clutter. Overview and comparison screens remain full-page. | Accepted | Settings/admin surfaces |
| UX-008 | Similar concepts must use shared placement and components: server/credential/policy rows, problem lists, review steps, advanced panels, confirmation modals, and empty/error states. | Accepted | Core WebUI and module WebUIs |
| UX-009 | Preflight and diagnostics are product UX. Validation, policy, permission, dependency, and capability failures must be written for operators before exposing internal details. | Accepted | Installer, connectors, policy, package import |
| UX-010 | Context, decision, and consequence must be visible together for actions that affect rights, duties, records, money, communication, retention, external systems, or workflow state. | Accepted | Workflow, admin, portal, policy, connector, records, payments |
| UX-011 | Navigation is not consent. Route changes, panel switches, and passive selection must not execute consequential actions without an explicit action surface. | Accepted | All WebUI surfaces |
| UX-012 | Automated actions must remain inspectable. The UI must show the system actor, trigger, policy result, observed effects, and failure/manual-intervention state when automation changes administrative state. | Accepted | Workflow, automation, connectors, tasks, audit |
| UX-013 | Contestable decisions must expose provenance. Denials, locks, generated outputs, calculated defaults, policy decisions, access decisions, and retention decisions need a reachable source path. | Accepted | Policy, access, templates, workflow, retention, records |
| UX-014 | Retraction, expiry, undo, rollback, and delete controls must state the real limit of the operation. Corrective or future-only actions must not be described as if they undo already observed effects. | Accepted | Postbox, files, records, installer, workflow, payments |
| UX-015 | Core owns the platform appearance contract. Modules must use shared CSS tokens and shared controls for theme-aware UI; they must not define independent light/dark palette systems. | Accepted | Core shell and all module WebUIs |
| UX-016 | Full-page create/edit surfaces keep Discard and the named Save … action in the upper-right page action cluster, with Save at the far right. Their position remains stable through validation and loading states. |
Accepted | All full-page create/edit surfaces |
| UX-017 | Table row actions use icon-only controls in a stable rightmost column and intent order: inspect/open, edit, copy, transfer/share/download, retry/restore, destructive action last. Every icon requires a translated accessible name and tooltip. | Accepted | All structured tables |
| UX-018 | A collapsible card containing only one table gives the table the card's full available body, without decorative inner wrappers, duplicate padding, max-widths, or nested scrolling. | Accepted | List, detail, workflow, and configuration surfaces |
| UX-019 | Focused-view precedence is manual session pin, current-task suggestion, user default, role/tenant default, then the full interface. The active source and a full-interface escape remain visible; a suggested view never changes authorization or implies consent. | Accepted | Shell, modules, future workflow composition |
| UX-020 | Centrally exported Core components are mandatory wherever their contract covers the interaction. A custom reusable control, presentation primitive, or module-local substitute requires explicit product-owner authorization, a narrowly specific purpose, and documented rationale and scope; it must not duplicate a central component. | Accepted | Core WebUI and all module WebUIs |
| UX-021 | A collection-wide create action belongs in that collection's page heading and is not duplicated in a persistent side panel. When a side panel is the creation surface, it is present for the creation view only. | Accepted | List-detail, directory, and create surfaces |
| UX-022 | Use central Card components for logical sections, DataGrid for tabular row collections and their ordered actions, and ToggleSwitch for boolean settings. Repeatable people/contact editors use one structured row per person with name, email address, and actions; free-form address parsing is reserved for an explicitly designed bulk-import flow. |
Accepted | All WebUI forms and collection editors |
| UX-023 | FieldLabel is the standard label/help surface for every field that is not self-explanatory. Any field rendered without it must be recorded in the omission register below, including its accessible-name source and rationale. Users may hide inline help markers through their persisted interface preference; the field label itself remains visible. |
Accepted | All Core and module forms |
| UX-024 | Explicit Discard actions and dirty in-application navigation use the shared UnsavedChangesProvider dialog. A page registers save/discard behavior with useUnsavedDraftGuard; its Discard button calls requestDiscard, and route changes use useGuardedNavigate or requestNavigation. |
Accepted | All create/edit surfaces |
| UX-025 | window.alert and the global alert function are prohibited. A narrowly necessary exception requires product-owner authorization and an entry in the alert exception register before implementation. |
Accepted | All WebUI code |
| UX-026 | A table defines one stable ordered action set. A row-level unavailable action remains in its normal position and is disabled, preferably with disabledReason; structurally irrelevant actions are omitted for the entire table. Empty rows reserve the same slots so their Add action stays in the normal left-most action position. |
Accepted | All structured tables |
Confirmed Implementation Decisions
These decisions were accepted on 2026-07-09 for the first implementation slice. They shape reusable components and screen structure. Future changes must revise this section and update affected screens.
DUE-001: Primary Admin Configuration Shell
Decision: admin/configuration surfaces should standardize on a two-zone layout.
- Left or top area: searchable overview/list, status, and primary actions.
- Main area: selected item summary and common settings.
- Modal/wizard: create, connect, edit, test, review, and confirm actions.
- Collapsed advanced panels: rarely used technical fields.
Use this for file connectors and mail servers first, then migrate policy, retention, API keys, and module operations.
DUE-002: Wizard Step Model
Decision: standard wizard steps and names use this baseline:
- Choose type or scope.
- Enter essentials.
- Discover or test.
- Configure ownership and policy.
- Review changes and blockers.
- Save or submit for operator action.
Not every wizard needs every step, but flows should use these names and order where applicable.
This applies to explicit assisted setup, onboarding, import, preflight, and risky multi-step operations. It is not the default shape for ordinary create or edit dialogs.
DUE-003: Explanation Placement
Decision: richer explanations should use this placement model:
- Short helper text below labels only when it prevents common mistakes.
- Tooltips for icon-only controls and compact terms.
- Expandable "Why?" or "Details" blocks for contextual explanations.
- Right-side detail panel or review step for preflight/provenance/diagnostics.
Avoid permanently visible paragraphs inside dense admin cards.
DUE-004: Advanced Options Contract
Decision: advanced options are fields that are needed for control, compatibility, or diagnostics but are not part of the common setup path.
- protocol-specific endpoints, ports, path overrides, TLS/signing toggles, timeout/retry tuning, raw headers, migration/destructive flags, and fallback compatibility settings are advanced.
- names, descriptions, provider type, base URL, ownership, policy mode, and basic credentials are not advanced.
Advanced fields must still be editable through typed controls.
DUE-005: Blocker Language Contract
Decision: all disabled or blocked primary actions should use a shared structured reason object.
Shape:
summary: short plain-language reason.details: optional explanation.required_action: what needs to happen.actor: who can do it, for example system administrator or tenant admin.target: where to go or which setting/capability is missing.technical_details: optional expandable developer/operator data.
For simple missing required fields, highlight the fields and put the structured reason in a compact hover/focus bubble on the disabled primary action instead of adding a large persistent warning block.
DUE-006: First Migration Surface
Decision: convert file connectors first, then mail servers. They share the same server/credential/policy model, are high-value, and will prove the reusable patterns quickly.
DUE-007: Adaptive Create/Edit Forms
Decision: ordinary create/edit dialogs should show the full editable state in an adaptive form, not force a linear wizard.
- The user chooses a type, provider, credential mode, or policy mode.
- The dialog immediately adjusts to show only the fields relevant to that state.
- Editing an existing object uses the same field grouping and layout as creating it, so users can recognize the state they configured.
- Discovery and test actions must give visible feedback in the same dialog: directly usable, discovered alternative, credentials needed/rejected, or not found with the next action the user can take.
- Wizard shells remain available for assisted setup, first-run guidance, imports, discovery-heavy flows, and operational preflight workflows.
DUE-008: Platform Theme Contract
Decision: the WebUI shell exposes a small, stable appearance contract based on shared CSS tokens and persisted user preference selection.
- Core applies
system,light, anddarkpreferences at the document root. - Core owns shared tokens such as
--bg,--bar,--panel,--surface,--line,--line-dark,--text,--text-strong,--muted, semantic status colors, radii, shadows, and disabled-control colors. - Modules must style new UI with these tokens and shared controls. Module-local CSS may tune layout and spacing, but it must not introduce a separate appearance system.
- Appearance controls live in user settings first. Tenant defaults and policy enforcement can be added later without changing the token contract.
- Visual preview in settings is illustrative; it must reflect token families, not become a second theme implementation.
DUE-009: Central Component And Exception Contract
Decision: module interfaces are compositions of the components exported by
@govoplan/core-webui. When Core already owns the matching interaction, using
the central component is required rather than preferred.
A route or domain-specific page composed from central components is ordinary module composition. A new reusable UI control, presentation primitive, or module-local substitute is a custom component. Before one is implemented, the product owner must explicitly authorize it and the owning decision or issue must record:
- its single, narrowly defined purpose and intended consumers
- why central components or their composition cannot meet that purpose
- the permitted scope and the boundary it must not grow beyond
- accessibility, reachable states, theme behavior, and test expectations
- whether the component remains domain-owned or is a candidate for Core
Custom components must not duplicate, fork, or cosmetically replace a central component. An existing local implementation does not grant an exception. If a central contract later covers the need, migrate to it unless the product owner explicitly retains the exception.
DUE-010: Scheduling Request Reference Composition
Decision: Scheduling requests provide a concrete reference application of the universal placement and component rules.
- The persistent left panel stacks
My scheduling requestsandScheduling requests for me; it is list context, not a second creation affordance. - The left panel's
Scheduling requestsheader owns oneAddaction. It opens the shared view/create/edit surface in the right main panel. - Basic information, Calendar integration, candidate slots, and participants
use the central
Cardcomponent as four logical sections. - Candidate slots and participants use the central
DataGrid, including its standard row-action placement and order. - Calendar integration uses the central
ToggleSwitch, with its dependent controls shown when enabled. - Each participant is edited as one structured row with name, email address, and actions. The normal editor does not parse a free-form list of addresses; that interaction requires a separate, explicitly designed bulk-import flow.
Equivalent list/create/edit surfaces use the same underlying rules. These are not Scheduling-local component variants.
DUE-011: Field Help, Discard, And Table Action Contracts
Decision: the central components own these interactions; modules compose them instead of reproducing their behavior.
FormFieldandToggleSwitchalready renderFieldLabel. Direct field compositions useFieldLabelexplicitly when the meaning or limitation is not self-explanatory.helpcontent is contextual guidance, not the accessible name. The persistedshow_inline_help_hintsuser preference hides only theInlineHelpmarker by applyingui-hide-help-hintsat the document root.- A dirty editor registers once with
useUnsavedDraftGuard. An explicit Discard button callsuseUnsavedChanges().requestDiscard(afterResolve); SPA navigation usesuseGuardedNavigateorrequestNavigation. Both paths show the same shared unsaved-changes dialog. A browser tab/window unload remains a browser-controlled confirmation because browsers do not permit a custom modal at that boundary. TableActionGroupreceives the table's stable action set. UsedisabledanddisabledReasonfor row state; omit an action only when that action does not belong to the table.minimumSlotsreserves trailing positions for an empty row.DataGridEmptyActiondoes this for the standard add/move/remove layout.- A paginated
DataGridhas exactly one query owner. Client mode receives the complete logical row set and applies filtering and sorting before slicing a page. Server mode receives only the loaded page, requiresonQueryChange, and the backend applies every emitted filter/sort before pagination while returningtotalRowsfor the filtered result. Server list filters declare their complete option domain instead of deriving it from the loaded page. External filter affordances such as summary-count shortcuts update the grid'squerycontract; the grid header controls and backend query therefore always display and execute the same filter state. - Feedback and confirmation use
Dialog,ConfirmDialog, orDismissibleAlert. They never fall back towindow.alert.
FieldLabel Omission Register
Every Core field surface that intentionally does not render FieldLabel is
listed here. Module repositories keep an equivalent register in their durable
UI documentation until a central cross-repository audit is available.
| Core scope | Why FieldLabel is omitted |
Accessible/context label source |
|---|---|---|
PasswordField, ColorPickerField, DateField, TimeField, and DateTimeField input internals |
These are label-neutral composite primitives and are placed inside FormField/FieldLabel by the consuming form. Rendering another label inside the primitive would duplicate it. |
Enclosing label; a direct consumer must pass an accessible name and record that direct composition here. |
ToggleSwitch native checkbox |
The shared component already renders its visible text through FieldLabel; the native input must not render a second label. |
The enclosing native label and derived aria-label. |
FileDropZone hidden file input |
The input is an implementation detail of the labelled keyboard-operable drop target. | Drop target text and inputLabel/aria-label. |
AdminSelectionList and DataGrid list-filter checkboxes |
Each option is self-explanatory and already enclosed by its visible option label. | Enclosing native option label. |
EmailAddressInput compact Name and Email fields |
These two conventional fields are self-explanatory in the compact address popover; richer address guidance belongs to the enclosing field. | Visible native labels; the free-form editor also has a descriptive aria-label. |
DataGrid page-size, filter, and inline cell editors |
The surrounding column header/filter heading supplies field context; repeating a labelled help marker in every cell would add noise. | Column header, filter heading/native label, or generated cell aria-label. |
| Retention-policy value controls | PolicyRow owns the field label, help, effective value, and provenance for its control. |
The containing PolicyRow label/help contract. |
Alert Exception Register
No window.alert or global alert exception is authorized.
Implementation Sequence
| Phase | Scope | Output |
|---|---|---|
| 0 | UX inventory | List every admin/settings/configuration surface, classify it, and record whether it violates a binding decision. |
| 1 | Core primitives | Shared wizard shell, advanced panel, help affordance, blocker callout, problem list, review step, and discovery/test result components. |
| 2 | File connectors | Adaptive create/edit for provider/server, credential, discovery/test, ownership/policy, plus optional assisted wizard later. |
| 3 | Mail servers | Same adaptive pattern as files, adapted to server/credential/policy and test-send/test-login behavior. |
| 4 | Policy/retention editors | Effective value first, provenance visible, override/edit in modal, blocked edits explained. |
| 5 | Module/package operations | Step-based install/uninstall flow with preflight, maintenance, daemon handoff, migration, and rollback explanation. |
| 6 | Remaining settings/admin screens | Apply inventory findings by priority and remove one-off layouts. |
Current Surface Inventory
This is the phase-0 inventory baseline. It should be extended as each screen is converted or reviewed.
| Surface | Repository | UX State | Next Action |
|---|---|---|---|
| File connector settings | govoplan-files |
First adaptive modal slice started: connections and credentials now use full-state create/edit forms with conditional fields, advanced panels, and blocker primitives. Wizard shell is retained for later assisted setup. Central policy card still needs a layered editor. | Finish provider discovery/test-in-flow, then convert policy editing. |
| Mail server settings | govoplan-mail / govoplan-core |
Uses the shared server/credential model visually, but create/edit still needs the same adaptive pattern as files. | Migrate to adaptive server/credential/policy dialogs, with optional assisted wizard later. |
| Connector policy/effective rows | govoplan-core, module UIs |
Effective-policy direction exists, but many editors still expose broad option sets. | Put effective value first, move overrides into modal, and explain blocked edits. |
| Admin module management | govoplan-admin |
Has preflight concepts, but operational choices are still technical and dense. | Convert install/uninstall/package changes to operator wizards. |
| Configuration packages | govoplan-admin |
Catalog/import work exists, but package editing can still drift toward technical fields. | Add guided import/review/problem-list flow. |
| Retention and privacy | govoplan-core |
Functional editor exists; consequence language and provenance can be stronger. | Layer advanced retention options and add review for broad changes. |
| API keys | govoplan-access / admin UI |
Security-sensitive creation needs least-privilege guidance. | Add scoped creation wizard with expiry/owner review. |
| User settings | govoplan-core |
Preferences persistence exists; interface navigation issue was fixed earlier, but the surface still needs UX review. | Keep simple sections, remove double-click traps, and add quiet explanations. |
Impact Index
| Surface | Current Risk | Expected Pattern |
|---|---|---|
| File connectors | Too many technical fields and unclear setup order. | Adaptive create/edit form with optional assisted wizard, discovery/test, credential binding, policy review, and advanced protocol panel. |
| Mail servers | Similar server/credential/policy concepts risk diverging from files. | Same tree/list and adaptive server/credential/policy model as file connectors. |
| Connector credentials | Security-sensitive details can overwhelm users. | Separate credential flow with secret-reference language and test result explanation. |
| Policy and effective settings | Users need to know why a value is inherited or locked. | Effective row first, source/provenance, local override action, actionable blocked reason. |
| Module install/uninstall | Operationally risky, currently inherently technical. | Operator wizard with preflight, maintenance, daemon handoff, review, and rollback explanation. |
| Configuration packages | Could become package JSON editing. | Package catalog/import wizard using provider data requirements and problem lists. |
| Retention/privacy | High-risk settings need explanation and provenance. | Layered editor with plain-language consequences and review. |
| Automation/workflow commands | Hidden side effects would undermine accountability. | Action/effect preview, system-actor display, command record, retry/quarantine/manual states, and audit links. |
| Postbox and encrypted communication | Retraction and access can be misunderstood. | Honest key-fetch/decryption state, expiry limits, recipient/device access provenance, and delivery evidence. |
| API keys | Security-sensitive creation and scope selection. | Scoped creation wizard, least-privilege suggestions, clear expiry/owner explanation. |
| User settings | Needs clarity and persistence across profile/interface/preferences. | Simple settings sections with immediate feedback and no double-click navigation traps. |
Review Checklist
Every new or changed admin/configuration surface should answer:
- What is the common path, and is it visible without noise?
- Which fields are advanced, and are they collapsed by default?
- Is every configuration value editable through typed controls?
- Does the flow avoid JSON as the primary editor?
- Does the screen explain disabled actions and failed validation in plain language?
- Does it say who can fix a blocker and where?
- Does it reuse existing core patterns for wizard steps, problem lists, modals, help, and review?
- Is there a review or preflight step before broad, destructive, or risky changes?
- Does the action surface show consequence, reversibility, and audit evidence when rights, duties, records, money, communication, external systems, or workflow state are affected?
- Does the surface use every applicable central Core component? If it contains a custom component, is the product-owner authorization, narrow purpose, rationale, scope, and non-duplication evidence recorded?
- Is a collection-wide create action in the collection heading rather than duplicated in a persistent side panel?
- Are logical sections, tabular collections, boolean settings, and repeatable
people/contact rows composed with
Card,DataGrid,ToggleSwitch, and one structured row per person respectively? - Does every non-self-explanatory field use
FieldLabel, and is every omission recorded with its rationale and accessible-name source? - Do explicit Discard and dirty navigation use the shared unsaved-changes registration/dialog rather than a page-local confirmation?
- Does every row retain the table's action set in the same order, disabling unavailable actions and reserving the same empty-row slots?
- Is feedback rendered with a central dialog/alert component, with no
unauthorized
window.alertor globalalertcall? - If automation is involved, can the user see the trigger, system actor, observed effects, and failure/manual-intervention state?
- Are technical details available without being the first thing the user sees?
Revision Rule
When a UX decision changes:
- Update this ledger.
- Update the affected shared components.
- Update existing screens listed in the impact index.
- Add or update Gitea issues for any remaining surfaces that still follow the old decision.
- Sync the wiki.