01 — Foundation

Save state is part of trust

Users should always know whether their work is safe, in progress, or lost.

Save states communicate whether changes are stored, still uploading, or failed. Silent autosave without feedback creates anxiety. Mystery “Saved” flashes with no context feel like the product is guessing.

02 — States

The states users need

Cover the full lifecycle — not only the happy path.

  • unsaved changes — clear when the form is dirty and leaving might lose work
  • saving — in progress, with disabled submit or “Saving…” on the control
  • saved — confirmation that matches the scope (“Draft saved”, “Published”)
  • failed — specific error and retry without silent data loss
<p role="status" aria-live="polite" id="save-status">
    All changes saved.
</p>
<button type="submit" aria-describedby="save-status">Save</button>

03 — Autosave

Autosave without anxiety

Background saves should be visible, debounced, and recoverable when they fail.

  • show last saved time or status — “Saved 2 minutes ago” beats invisible magic
  • debounce rapid edits; avoid hammering the server on every keystroke
  • handle conflicts — two tabs editing the same record need a clear resolution path
  • warn before navigation when unsaved work would be lost

04 — Accessibility

Announce without noise

Screen reader users need the same confidence sighted users get from status text.

  • use role="status" or aria-live="polite" for non-urgent updates
  • do not announce every autosave tick — batch or summarise meaningful changes
  • failed saves use assertive live regions only when users must act immediately

05 — Review

Before you approve

A short checklist for save states in code review.

  • users can tell saved, saving, unsaved, and failed apart at a glance
  • autosave is visible; conflicts and navigation loss are handled
  • status is announced appropriately — see also Loading States and Confirmation