Save States
Last updated:
Practical patterns for saved, saving, unsaved, and failed — including autosave users can trust.
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"oraria-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