| UI or UX | UI + UX - Unbounded loading anti-pattern | UI + UX - Bounded content loading placeholder | UI + UX - Recoverable failure surface |
| UI guidance | Replace an unlabeled endless spinner with a bounded loading surface that names the operation, preserves the affected context, and changes state after the wait threshold. | Keep skeleton dimensions stable, mark the affected region busy, and use subtle or reduced-motion-respecting animation only while loading is unresolved. | Render a persistent error region near the affected content with a specific failure heading, plain-language cause, preserved context, and recovery actions. |
| UX guidance | Help users decide whether to wait, retry, leave safely, use stale data, or escalate instead of forcing them to infer system health from animation alone. | Reduce uncertainty and layout shift while predictable content loads, then resolve clearly to real content, empty state, or error state. | Match the next action to the failure cause: retry transient failures, edit correctable input, use cached fallback for read-only continuity, or provide support reference when recovery is outside the UI. |
| Good UI | Billing data is loading shows the affected account, elapsed wait, and actions for Retry, Use cached values, and Contact support after timeout. | The interface shows a clear action and state. | A failed save state keeps the draft visible and labels the support reference separately from the user-facing explanation. |
| Bad UI | A Save button turns into a spinner forever, leaving the user unable to cancel, retry, or know whether the save happened. | Skeleton rows look like clickable report cards and receive focus before content exists. | Tiny transient toast for a blocking failure. |
| Good UX | The user can wait briefly, see that billing data is delayed, open cached values, retry once, or escalate with a reference. | Users see that reports are pending, then can switch the demo to loaded, empty, or error outcomes on a bounded path. | User input and filter context are preserved after failure, and retry returns to recovered content or a clear still-failed state. |
| Bad UX | A failed backend response is hidden behind a permanent spinner. | Large layout shift after content arrives. | Clearing work after save failure. |
| Best fit | Use this anti-pattern entry to audit loading, saving, syncing, uploading, report generation, billing retrieval, AI generation, and import flows that can hang. | The content shape is predictable. | A system or task failure blocks expected content or action. |
| Avoid when | A short spinner is clearly labeled, tied to a specific action, and guaranteed to transition quickly. | A specific progress indicator or blocking message is required. | Nothing exists yet and the state is expected. |
| Required state | Initial pending state that names the operation and affected object. | Initial skeleton placeholder state with region marked busy. | Normal expected state before failure. |
| Accessibility burden | Give progress indicators accessible names that identify the operation or affected region. | Mark the loading region busy or provide concise status text. | Use appropriate alert or status semantics for newly appearing critical errors. |
| Common misuse | Animating a full-page spinner forever after a request times out. | Showing skeletons forever. | Using a transient toast for critical errors. |