Clicking Add to Cart with no visible response leaves the shopper guessing whether the click registered. They click again, then again, producing duplicate line items, or they give up and leave. Silent failures are worse: the network request 500s, the cart stays empty, and the next page load reveals nothing was added. This destroys trust in the checkout flow and is one of the most common causes of cart-abandonment micro-frustration documented in Nielsen Norman usability studies.
Medium because the defect frustrates every shopper and causes duplicate-add bugs, though the cart data itself is not corrupted.
Wrap the add-to-cart handler in a loading state, render a disabled button while the request is in flight, and surface both success and error outcomes with a toast. Handle the catch branch explicitly — a console.log does not count as user feedback. Implement this in src/components/AddToCartButton.tsx.
setIsLoading(true)
try { await addToCart(productId); toast.success('Added to cart') }
catch { toast.error('Failed to add item') }
finally { setIsLoading(false) }
ID: ecommerce-cart-ux.cart-management.add-feedback
Severity: medium
What to look for: Count all "Add to Cart" button instances across the codebase (product pages, product cards, quick-view modals). For each instance, classify the feedback mechanism as one of: (a) loading/disabled state on button, (b) toast/notification, (c) cart count badge update, (d) modal confirmation, (e) none. Quote the handler function name and file path for each. Check that at least 1 error-state feedback path also exists (not just success).
Pass criteria: At least 1 visual feedback mechanism fires within 1 second of clicking "Add to Cart" — button loading state, toast notification, or cart count badge update. Both success and error states are handled (at least 1 catch or error callback exists). Report even on pass: "Found X add-to-cart buttons across Y files. All X use feedback mechanism Z."
Fail criteria: No feedback after clicking "Add to Cart" — user cannot tell if the action succeeded or failed. A console.log-only error handler does not count as user-visible feedback.
Do NOT pass when: Feedback exists only for success but not for errors — the user sees nothing when the network request fails.
Skip (N/A) when: The project has no "Add to Cart" button (e.g., catalog-only site, wishlist-only, or request-a-quote model).
Detail on fail: Example: "Found 3 AddToCart buttons in src/components/. 0 of 3 show loading state or success toast. Error path logs to console only."
Cross-reference: For error handling patterns and user-visible error states, the Error Resilience audit covers error boundaries and retry logic. For accessibility of toast notifications, the Accessibility Fundamentals audit covers ARIA live regions.
Remediation: Add visual feedback in your add-to-cart component, typically at src/components/AddToCartButton.tsx:
// src/components/AddToCartButton.tsx
function AddToCartButton({ productId }) {
const [isLoading, setIsLoading] = useState(false)
const { addToCart } = useCart()
const handleClick = async () => {
setIsLoading(true)
try {
await addToCart(productId)
toast.success('Added to cart!')
} catch (error) {
toast.error('Failed to add item')
} finally {
setIsLoading(false)
}
}
return (
<button onClick={handleClick} disabled={isLoading}>
{isLoading ? 'Adding...' : 'Add to Cart'}
</button>
)
}