C.W.K.
Stream
Lesson 03 of 04 · published

Pending, Sending, Answered, Failed — All Visible

~11 min · ux, state-visibility, honest-ui, feedback

Level 0Dead Zone
0 XP0/32 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"A spinner that never resolves is a lie with an animation. Show the real state, even when the real state is 'waiting'."

The UI Must Not Out-Confident the System

Honest offline isn't only a data rule; it's a UI rule. The interface must never claim more certainty than the system actually has. If a turn is pending because you're offline, the screen must say waiting — not show a spinner that implies work is happening, and definitely not show a checkmark that implies it's done. The four internal states from Track 2 aren't just for the code; each one deserves a distinct, truthful surface the user can read at a glance.

Four States, Four Honest Faces

  • Pending — captured, not yet sent (often offline). Say so: "Saved. Waiting to reach Pippa." This is a calm, safe state, and the UI should feel calm, not alarmed.
  • Sending — actively delivering. A spinner is honest here, because work really is happening right now.
  • Answered — a real reply materialized from a canonical call. Only now does the answer appear.
  • Failed — delivery attempted and errored. Show it plainly with a retry affordance; the turn is safe and re-sendable, and the UI should convey exactly that, not panic.

The discipline is one-to-one: no UI state should exist that doesn't correspond to a real system state, and no system state should be invisible. When those line up, the user's trust is earned continuously — what they see is always what's true.

Why Visible Beats Optimistic

Optimistic UI — showing success before it's confirmed — is popular because it feels fast. But for a client whose whole value is trust under bad conditions, optimism is a small lie that compounds. Show a message as "sent" before it's delivered and, on a flaky link, the user builds a false model of what got through. Pippa Go prefers visible over optimistic: a slightly less snappy pending badge that's always true beats a satisfying checkmark that's sometimes false. The badge is the promise, rendered.

Code

One truthful label per real state·typescript
function statusLabel(turn: PippaGoTurn): { text: string; spinner: boolean } {
  switch (turn.syncStatus) {
    case "pending":  return { text: "Saved · waiting to reach Pippa", spinner: false };
    case "sending":  return { text: "Sending…",                      spinner: true  };
    case "answered": return { text: "Answered",                      spinner: false };
    case "failed":   return { text: "Couldn't reach Pippa · tap to retry", spinner: false };
  }
}

// The spinner is true ONLY for 'sending' — the one moment work is really happening.
// 'pending' is calm and honest, not a fake in-progress animation.

External links

Exercise

Design the four status badges for a Pippa Go turn: exact copy, whether each shows a spinner, and what tap-action (if any) each offers. Then stress-test them: on a flaky connection that flips online/offline three times, does any badge ever claim more than the system knows? If a badge could lie during that flapping, redesign it until it can't.
Hint
The danger states are the transitions. If 'sending' can get stuck visible after the connection drops, it becomes a lying spinner — so a dropped link during 'sending' should transition to 'pending' or 'failed', never leave a spinner spinning over nothing.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.