Skip to content

Image Gen disables its entire prompt form during every backend status probe, so the page's primary CTA is dead on first paint #5671

Description

@atomantic

ProblemImageGen.jsx threads statusLoading into disabled on 14 controls, including the prompt textarea, the negative-prompt textarea, the universe picker and the style-preset picker — all of which are pure client-side form state that has nothing to do with whether a Stable Diffusion backend answered. statusLoading is set true on mount and again on every backend-chip / model change, and the code's own comment says the probe can take a long time ("the initial external probe timing out against an unconfigured SD API URL"). The result: the user lands on /media/image, the form that fills the entire above-the-fold region is greyed out and unresponsive, and it goes dead again every time they switch backends. The sibling page VideoGen.jsx — same shell, same probe — gates exactly one control (the refresh button), which is the correct behaviour and the model to copy.

Evidenceclient/src/pages/ImageGen.jsx:286:

  const refreshStatus = useCallback((mode, localModelId) => {
    const myToken = ++statusRequestToken.current;
    setStatusLoading(true);
    getImageGenStatus(mode, mode === IMAGE_GEN_MODE.LOCAL ? localModelId : undefined)

and the form, client/src/pages/ImageGen.jsx:1291-1320:

          <UniverseStylePicker value={selectedUniverse?.id || ''} onChange={setSelectedUniverse} disabled={statusLoading} />
          <StylePresetPicker value={stylePreset?.id || ''} onChange={setStylePreset} disabled={statusLoading} />
          
              <AutoSizeTextarea value={prompt} onChange={(e) => setPrompt(e.target.value)} rows={3}
                disabled={statusLoading}
                 placeholder="Describe the image you want to generate..." />

grep -c 'disabled={statusLoading}' client/src/pages/ImageGen.jsx → 14. The same grep on client/src/pages/VideoGen.jsx → 1 (:841, the Refresh status button).

Plan

  1. In client/src/pages/ImageGen.jsx, introduce const probeGated = statusLoading; and keep it ONLY on the controls whose behaviour genuinely depends on the probe result: the Refresh-status button (:1274), the BackendChipStrip (:1265), and the Generate submit button. Decision: the probe determines which backend can run, not what the user can type, so only backend-selection and submit are gated — this matches VideoGen and removes the dead-form window entirely.
  2. Remove disabled={statusLoading} from the remaining controls: UniverseStylePicker (:1291), StylePresetPicker (:1296), both AutoSizeTextarea prompt fields (:1309, :1319), PromptEnhancer (:1333), PromptFromMedia (:1340), and the parameter inputs at :1352, :1379, :1400, :1434, :1448, :1463.
  3. Keep the Generate button disabled while statusLoading is true so the user cannot submit against an unknown backend, and give it the existing "Checking…" label so the reason is visible rather than a mystery grey button.
  4. Leave the status pill's statusLoading ? … 'Checking {effectiveMode}…' branch at :1235 as-is — it is the correct progressive-disclosure affordance.

Tests

  • Extend client/src/pages/ImageGen.test.jsx with a test that renders with getImageGenStatus pending and asserts the prompt textarea is NOT disabled while the Generate button IS. Uniquely catches a regression that re-couples form input to the probe.
  • Add a second case asserting that after the probe resolves with connected: false, Generate stays disabled and the prompt textarea stays enabled.

Acceptance criteria

  • grep -c 'disabled={statusLoading}' client/src/pages/ImageGen.jsx is at most 3.
  • On a cold load of /media/image the user can type a prompt before the status pill resolves.
  • Switching backend chips no longer blanks out the form.

Out of scope — the status-probe implementation, backend-readiness gating logic in imageGenReadiness, and VideoGen's own gating.


Filed by a /do:better --scan-only --issues audit (2026-09-01). Category: ux · Severity: high · Files: client/src/pages/ImageGen.jsx:286, client/src/pages/ImageGen.jsx:1309, client/src/pages/ImageGen.jsx:1319, client/src/pages/ImageGen.jsx:1291, client/src/pages/VideoGen.jsx:841

All labels already exist in the repo; do NOT create labels. Never add planner:* labels.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingeffort:lowEffort: lowmodel:mediumModel size: mediumplanTracked by /do:replanplanner:fable-5.1Plan authored by the Fable 5.1 modelseverity:highuxProposed from a UX/design audit

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions