From harness-claude
Guides UI feedback patterns for user actions: immediate vs delayed responses, optimistic/pessimistic updates, progress indicators, toasts/snackbars/banners, undo vs confirm.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> System response design — immediate vs delayed feedback, optimistic updates, progress indicators, confirmation patterns, undo vs confirm, toast/snackbar/banner
Designs UI feedback for user actions: immediate responses, confirmations via toasts/checkmarks, status indicators, notifications across visual/text/audio/haptic channels with hierarchy and accessibility best practices.
Generates specific success confirmation messages, calibrated celebrations for milestones, and next-step prompts for UI toasts, emails, and undo links after actions.
Adds loading, empty, error, and success feedback states to StyleSeed components and pages using mobile-first rules. Use for async data-dependent UIs.
Share bugs, ideas, or general feedback.
System response design — immediate vs delayed feedback, optimistic updates, progress indicators, confirmation patterns, undo vs confirm, toast/snackbar/banner
Every user action must produce visible feedback within 100ms. This is Jakob Nielsen's foundational threshold: actions with feedback under 100ms feel instantaneous. Between 100ms and 1 second, the user notices a delay but maintains flow. Over 1 second, the user's attention breaks and they need a progress indicator. Over 10 seconds, they need percentage completion or a time estimate. No action should ever produce zero feedback — a silent button click is a broken interface. Even if the backend operation takes seconds, acknowledge the click immediately with a visual state change (button press, spinner start, text update).
Choose optimistic or pessimistic updates based on operation reversibility and failure rate. The decision matrix:
| Condition | Strategy | Example |
|---|---|---|
| Reversible + low failure rate (<5%) | Optimistic | Slack message send, GitHub star |
| Reversible + high failure rate (>5%) | Pessimistic | File upload (network-dependent) |
| Irreversible + any failure rate | Pessimistic | Payment processing, account deletion |
| Irreversible + critical impact | Confirm first | Stripe charge, data export, user removal |
Optimistic updates show the success state immediately and roll back on failure. Slack displays your message in the channel instantly — if the server rejects it, the message shows a red warning icon with "Not delivered. Click to retry." The rollback is visible, actionable, and non-destructive. GitHub's star is optimistic: the star fills and the count increments on click, before the server confirms. If the server fails, the star unfills and the count reverts.
Use the toast/snackbar/banner taxonomy correctly. These three feedback containers serve different purposes and should not be used interchangeably:
Implement undo instead of confirmation for reversible destructive actions. Confirmation dialogs ("Are you sure?") are failure patterns — users click "Yes" reflexively without reading. Research by Aza Raskin (Mozilla) showed that confirmation dialogs prevent less than 5% of unintended destructive actions because users develop muscle memory for the confirm button. Undo is superior: let the action happen immediately, show a snackbar with an undo option, and give the user 6-10 seconds to reverse it. Gmail pioneered this with "Undo Send" (originally a 5-second window, now configurable to 30 seconds). The action feels fast (no dialog interruption) and the safety net is always visible.
Reserve confirmation dialogs for truly irreversible, high-consequence actions. The threshold: if the action cannot be undone AND the consequences are significant (data loss, financial transaction, permanent account change), use a confirmation dialog. Stripe uses a confirmation dialog for refunds — the dialog names the specific amount and customer, requires explicit confirmation, and cannot be undone. GitHub uses a typed-confirmation pattern for repository deletion: you must type the repository name to confirm, preventing both accidental clicks and confirmation-dialog muscle memory.
Design progress indicators based on operation characteristics. The decision procedure:
Stack feedback by urgency with a clear visual hierarchy. When multiple feedback messages compete for attention, use a priority system:
Never show a success toast while an error banner is active — the mixed signals confuse users about system state.
Place feedback at the point of action whenever possible. Inline feedback (next to the button that was clicked, below the field that has an error) is always more effective than remote feedback (a toast in the corner, a banner at the top of the page). The user's attention is already at the point of action — inline feedback requires zero eye movement. Stripe's form validation is entirely inline: error messages appear directly below the offending field, the field border turns red, and the error text describes exactly what is wrong ("Your card number is incomplete"). No toast, no banner, no modal — the feedback is exactly where the user is looking.
Optimistic updates require three components working together:
Immediate state mutation. On user action, update the local UI state before the server responds. This means the UI must have a local state layer (React state, Zustand, Vuex, etc.) that can be modified independently of server state. When the user clicks "like," set isLiked = true and likeCount += 1 in local state immediately.
Background server request. Simultaneously, send the mutation to the server. The request runs in the background while the user sees the success state.
Rollback on failure. If the server returns an error, revert the local state to its pre-mutation value AND show the user what happened. This is where most implementations fail — they revert silently, and the user does not understand why their action "undid itself." The correct pattern: revert the state, show a toast/inline error explaining the failure ("Could not save. Check your connection."), and offer a retry action. Slack implements this precisely: if a message send fails, the message stays visible but gets a red warning icon and "Not delivered — Click to retry."
Conflict resolution. When the server returns success but with modified data (e.g., the server sanitized the input), the local state must reconcile. Pattern: on server success response, overwrite local state with server state. This handles cases where the server modifies timestamps, normalizes text, assigns IDs, or applies business logic that changes the data from what the client optimistically displayed.
Toast positioning affects discoverability and readability. The conventions by platform:
Stacking rules. Never show more than 3 toasts simultaneously — beyond 3, users stop reading them. When a new toast arrives while 3 are visible, dismiss the oldest. Group identical toasts: if 5 "Item saved" toasts fire in rapid succession, show one toast with a count: "5 items saved." Vercel groups deployment status updates into a single notification that updates its content rather than spawning new toasts.
The undo window duration directly impacts user behavior:
During the undo window, the server-side action should be deferred (not executed until the window expires) or logged for rollback. Gmail's "Undo Send" actually delays sending the email — it does not recall an already-sent email. This is important: the undo must be reliable, which means deferring is safer than rolling back.
The psychological breakpoints for feedback timing, validated across decades of HCI research:
The Silent Click. A button that performs an action but provides no visual feedback — no state change, no toast, no animation. The user clicks, nothing happens, they click again (potentially duplicating the action), and eventually something changes with no connection to their click. Fix: every clickable element must change its visual state on click within one frame (16ms). Even if the backend response takes seconds, acknowledge the click with a press state, spinner, or "Saving..." text.
Success Theater. Showing a celebratory success state (checkmark animation, confetti, "All done!") before the backend has confirmed success. If the server then rejects the action, the user experienced a lie. Fix: if using optimistic updates, keep the success feedback proportional (subtle confirmation, not celebration) so that a rollback is not jarring. Reserve celebratory feedback for confirmed successes only.
The Error Novel. Displaying error messages that are paragraphs long, filled with technical details, and buried in a modal dialog that blocks all other interaction. Users do not read long error messages — they click "OK" to dismiss them. Fix: error messages should be one sentence maximum, written in the user's language, with a single clear action. Put technical details behind a "Show details" toggle for debugging purposes.
Confirmation Dialog Addiction. Using "Are you sure?" dialogs for every action: delete, archive, save, cancel, navigate away. Confirmation fatigue sets in after 2-3 dialogs and users click "Confirm" reflexively, defeating the purpose entirely. Fix: use undo for reversible actions, reserve confirmation for truly irreversible high-consequence actions (payment, permanent deletion, account changes), and never confirm non-destructive actions.
Feedback Channel Mismatch. Showing a success toast at the top-right corner of the screen while the user's attention is on a form at the bottom-left. The feedback fires but the user never sees it because it is outside their attentional focus. Fix: place feedback at the point of action. If you must use a remote notification (toast/banner), also provide inline feedback at the action source — a subtle checkmark next to the button, a field border color change, or an inline success message.
Slack Optimistic Messaging. When you send a message in Slack, it appears in the channel immediately with full formatting. The only hint that it has not been confirmed by the server is a subtle clock icon where the timestamp will appear. On server confirmation (typically under 200ms), the clock icon is replaced by the actual timestamp — most users never see the clock. On failure, the message stays visible but shows a red warning icon with "Not delivered — Click to retry." The message text is preserved, so the user does not need to retype anything. This is the gold standard for optimistic updates.
Vercel Deployment Progressive Feedback. A Vercel deployment provides feedback at every stage: (1) "Queued" with a gray status (immediate acknowledgment), (2) "Building" with a yellow animated dot and streaming build log, (3) "Deploying" with a blue animated dot, (4) "Ready" with a green checkmark, preview URL, and deployment summary. Each stage transition includes the elapsed time. If a build fails, the error state shows the exact line of the build log where the failure occurred, with syntax highlighting. The feedback is progressive, informative, and actionable at every stage.
Stripe Payment Confirmation. After a successful payment, Stripe shows: (1) an animated checkmark draw (300ms), (2) a confirmation message ("Payment successful"), (3) a receipt summary (amount, last 4 digits, date), and (4) clear next steps ("Return to [merchant]" button). On failure, Stripe shows: (1) the specific field with the error (card number, expiry, CVC), (2) a human-readable error message ("Your card was declined. Try a different payment method."), and (3) the form pre-filled with valid fields so the user only needs to fix the problem field. The feedback addresses both success and failure with equal design attention.
GitHub Typed Confirmation. For repository deletion, GitHub requires the user to type the full repository name (e.g., "cwarner/my-project") into an input field before the "Delete this repository" button becomes enabled. This pattern prevents both accidental clicks and confirmation-dialog muscle memory — you cannot type a repository name reflexively. The input includes real-time validation: the button remains disabled until the typed text exactly matches the repository name. This is appropriate for irreversible, high-consequence actions.
Linear Optimistic Status Updates. Changing an issue's status in Linear (e.g., "In Progress" to "Done") updates immediately in the local UI — the status icon changes, the issue moves to the correct column in board view, and any filter/sort recalculates. The server sync happens asynchronously. If the server rejects the change (rare), the issue reverts with a subtle error toast. Because Linear is a single-player tool in practice (your own issue statuses), the failure rate is extremely low, making optimistic updates the correct strategy.
For any interactive element, verify these feedback requirements: