Skip to content

diagram: sim-specs fields silently revert invalid input with no feedback #962

Description

@bpowers

Problem

In src/diagram/ModelPropertiesDrawer.tsx, SimSpecDraftField commits a draft on blur/Enter via resolveSimSpecDraft (src/diagram/sim-spec-draft.ts). When the draft is invalid -- e.g. a non-positive dt, or an empty/non-numeric start/stop time -- the resolver returns shouldCommit: false and the field silently discards the draft, snapping back to the model value on blur.

There is:

  • no inline error text explaining why the typed value vanished,
  • no aria-invalid / aria-describedby announcement for assistive tech,
  • no visual error state at all.

To the user (sighted or not), a typed value simply disappears.

Why it matters

  • Accessibility: screen-reader users get zero signal that their input was rejected; the field just reads back the old value.
  • UX: silent reversion is one of the most confusing failure modes in a form -- the user has no way to learn what input the field would accept.

Component

src/diagram -- ModelPropertiesDrawer.tsx (SimSpecDraftField), sim-spec-draft.ts (resolveSimSpecDraft), components/TextField.tsx.

Possible approach

The shared TextField component already wires aria-invalid + aria-describedby to its helperText automatically (added 2026-07-13 during the mobile/accessibility pass on the production-risk-burndown branch), so the fix is mostly plumbing: have SimSpecDraftField derive a validation message from the draft state (e.g. "dt must be a positive number") and pass error/helperText to TextField instead of silently reverting. Options for commit semantics:

  1. Keep the revert-on-blur behavior but show the error while the draft is invalid (message clears on revert or valid input), or
  2. Hold the invalid draft in the field with a persistent error message until the user fixes it or presses Escape.

Either way resolveSimSpecDraft likely wants to return a reason alongside shouldCommit: false so the message can be specific per field/failure.

Related but distinct

Context

Identified during the mobile/accessibility fix pass on the production-risk-burndown branch; deemed out of scope there because it changes commit/validation UX behavior rather than just wiring up existing error text.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions