Minimum viable pattern
- Visible status text near the action: “Sending…”, “Sent”, “Failed — Retry”. Don’t rely on an icon alone.
- Connection banner when offline: “Offline — changes will sync when back online.” Keep it calm and factual.
- Status announcement via
role="status"(polite) for changes like “Sending…” → “Sent”. - Busy state on the sending region while a request is in flight:
aria-busy="true". - Error is distinct + actionable: show a visible error with
role="alert"and a next step (Retry / Check connection). - Don’t rely on color: ensure states are distinguishable with text or shape.
Avoid announcement spam
- Debounce/coalesce repetitive messages (e.g., don’t announce “Offline” 10 times during flakey wifi).
- Prefer state transitions (“Sending…” → “Sent”) over continuous updates.
- If autosave is frequent, announce only meaningful milestones (e.g., error, first “Saving…”, “Saved”).
Design notes
- When offline, consider disabling “Send” with a reason (adjacent text) rather than letting the click fail silently.
- Retries should be easy and local: a Retry button near the failed action is better than a global toast.
- Respect
prefers-reduced-motion— if you use spinners, ensure motion can be reduced/disabled.
Related: Saving/autosave status note