Files
ForgeLM/.planning/phases/01-hf-model-discovery/01-UI-SPEC.md
T

8.7 KiB

phase, slug, status, shadcn_initialized, preset, created
phase slug status shadcn_initialized preset created
1 draft-state-ownership draft false none 2026-03-28

Phase 1 — UI Design Contract

Visual and interaction contract for frontend phases. Generated by gsd-ui-researcher, verified by gsd-ui-checker.


Design System

Property Value
Tool none — existing hand-authored CSS remains the source of truth for Phase 1; shadcn init deferred by default because this phase only defines the contract and does not require component-library adoption
Preset not applicable
Component library none — preserve existing runtime drawer, status card, inline chips, segmented controls, and footer actions
Icon library none required for Phase 1; use text labels and existing native controls before introducing new iconography
Font "Segoe UI Variable", "SF Pro Display", "IBM Plex Sans", system-ui, sans-serif

Spacing Scale

Declared values (must be multiples of 4):

Token Value Usage
xs 4px Status dots, inline separators, badge internals
sm 8px Input-support gaps, chip gaps, tight action spacing
md 16px Default field spacing, card padding, inline validation offset
lg 24px Section padding, grouped control spacing
xl 32px Drawer section breaks, footer-to-body separation
2xl 48px Major content breaks inside long settings drawers
3xl 64px Reserved for page-level or modal-level spacing only

Exceptions: minimum 44px input and button height for all primary interactive controls; destructive confirmation rows may use 12px vertical padding inside a 44px container.


Typography

Role Size Weight Line Height
Body 16px 400 1.5
Label 12px 700 1.4
Heading 20px 700 1.2
Display 28px 700 1.1

Color

Role Value Usage
Dominant (60%) #0a1016 App background, drawer shell, page canvas
Secondary (30%) #14202d Cards, grouped sections, saved/live reference surfaces
Accent (10%) #48a6ff Draft-state badges, selected segmented controls, focused fields, primary save CTA, latest-valid async result indicators
Destructive #f04040 Discard/revert confirmations, inline invalid-state borders, blocking save errors

Accent reserved for: dirty badges, active local-vs-remote selectors, selected model chips, the primary Save changes action, focus-visible outlines, and explicit live-vs-draft comparison labels; never use accent for all neutral buttons.


Copywriting Contract

Element Copy
Primary CTA Save changes
Secondary footer action Discard changes
Confirmation escape action Keep editing
Empty state heading No draft changes yet
Empty state body Edit any runtime setting to start a draft. Live runtime values keep updating until you choose to save or discard.
Error state Couldn't save your draft. Review the highlighted fields and try again — your unsaved changes are still here.
Destructive confirmation Discard changes: Discard this draft and return to the last saved settings? / Revert to saved: Replace all unsaved edits with the last saved values.

State Presentation Contract

  • The sticky drawer header is the first visual anchor on open: Draft settings title, dirty-state summary, and compact Live now status reference appear before any editable fields.
  • Opening the settings drawer creates a draft from the latest saved baseline and labels the drawer as Draft settings.
  • The current effective runtime state remains visible as Live now reference content in a secondary surface or read-only inline value for any field changed in the draft.
  • Dirty fields show three signals together: draft accent border, Draft label, and saved/live reference value below the control; color alone is never the only indicator.
  • Clean fields render with neutral borders and no draft badge.
  • Closing the drawer with unsaved edits hides the drawer and preserves the draft for the same app session; do not show a discard prompt on close or backdrop click.
  • Discard changes is the UI label for the Phase 1 full-form reset behavior locked in 01-CONTEXT.md; Revert to saved is the destructive confirmation label for completing that same reset. Per-field undo is out of scope.

Interaction Contract

  • Polling continues every 3 seconds for operational state, but polling updates may affect only live status surfaces such as readiness, process state, health messaging, and managed-library metadata.
  • Polling and async helpers must never overwrite dirty input values, selected folders, provider choice, or selected model while the draft is dirty.
  • Folder pickers, file pickers, model rescans, and validation passes are field-scoped updates only; they may update the invoked field and its dependent helper text, not the whole form.
  • If multiple async requests exist for the same field, only the latest response may update draft-facing UI; stale responses are ignored silently.
  • When a drafted value becomes invalid after rescan or validation, preserve the typed or selected value, mark the field invalid inline, and disable Save changes until fixed.
  • Resting footer actions for this phase are Save changes and Discard changes; selecting Discard changes expands an inline confirmation row with Keep editing and destructive Revert to saved. Local-runtime apply/start text remains separate and must always reflect whether saving is required first.
  • Busy states disable the triggering button, preserve current field values, and replace button text with in-place progress copy such as Saving..., Scanning..., or Searching....
  • Error messaging appears inline near the affected field when possible; fall back to a single drawer-level error banner only for save failures or cross-field failures.

Component Inventory

  • Drawer shell: right-side fixed drawer, full-height, max width 560px, blurred backdrop, sticky header and footer.
  • Primary focal point: sticky header block with Draft settings title, dirty-state summary, and Live now chip/status summary before the overview strip.
  • Overview strip: three read-only summary cells for current status, endpoint, and saved model.
  • Field groups: card-based sections with 16px internal padding and 18px corner radius.
  • Segmented controls: two-option mode switch with clear active state and no icon-only affordances.
  • Draft comparison rows: editable control on top, saved/live helper row beneath when dirty.
  • Inline validation: destructive border plus one-line message directly under the affected field.
  • Confirmation pattern: inline footer confirmation row for discard/revert actions instead of a separate modal.

Accessibility and Motion

  • All interactive controls must meet a 44x44px minimum hit target.
  • Keyboard order must follow visual order from overview to footer actions.
  • :focus-visible keeps the 2px accent outline already established in tauri-app/src/index.css.
  • Body copy and helper text must maintain at least 4.5:1 contrast against their surfaces.
  • State changes use opacity, border, and background transitions only, with durations between 150ms and 200ms.
  • Respect prefers-reduced-motion; suppress scale transforms and animated status pulses when reduced motion is enabled.

Source Notes

  • Locked from D:\Documents\Github\ForgeLM\.planning\ROADMAP.md: Phase 1 goal and success criteria require explicit live-versus-draft separation, explicit save/cancel/revert semantics, and draft-safe failure recovery.
  • Locked from D:\Documents\Github\ForgeLM\.planning\phases\01-hf-model-discovery\01-CONTEXT.md: draft lifecycle, preserved close behavior, field-scoped async updates, stale-request ignoring, and invalid-draft preservation.
  • Grounded in existing UI from D:\Documents\Github\ForgeLM\tauri-app\src\index.css, D:\Documents\Github\ForgeLM\tauri-app\src\features\runtime\components\RuntimeSettingsDrawer.css, D:\Documents\Github\ForgeLM\tauri-app\src\features\runtime\components\RuntimeStatusCard.css, and D:\Documents\Github\ForgeLM\tauri-app\src\features\runtime\components\RuntimeSettingsDrawer.tsx.
  • Brand output conventions referenced from C:\Users\Evandro\.config\opencode\get-shit-done\references\ui-brand.md.

Registry Safety

Registry Blocks Used Safety Gate
shadcn official none not applicable — shadcn not initialized
third-party none not applicable

Checker Sign-Off

  • Dimension 1 Copywriting: PASS
  • Dimension 2 Visuals: PASS
  • Dimension 3 Color: PASS
  • Dimension 4 Typography: PASS
  • Dimension 5 Spacing: PASS
  • Dimension 6 Registry Safety: PASS

Approval: pending