Add to cart
The button is operable and names the product context.
Commerce · Concept
An asynchronous action needs visible state and programmatic feedback without sending keyboard focus somewhere unexpected.
The principle
The button shows what it can do now. The status region explains what just happened.
State sequence
Do not jump directly from an initial label to a silent visual checkmark. Waiting, success, and failure are meaningful outcomes.
The button is operable and names the product context.
The button remains focused, blocks duplicate activation, and exposes a busy state.
Visible state and a complete status message communicate success or failure.
Interactive demo
Focus stays on the action button throughout the simulated request.
aria-disabled and aria-busy.role="status" region announces complete messages.$128
Cart: 0 items.
Do / Don’t
Status messages exist specifically to expose important updates that do not change context. Moving focus to every confirmation interrupts the person’s workflow.
A confirmation steals focus from the product, forcing the person to navigate back before continuing.
toast.focus(); // unnecessary context changeThe screen reader announces a complete message while the keyboard remains on the initiating button.
<p role="status" aria-atomic="true">Cart: 0 items.</p>
status.textContent = 'Cart: 1 item. Harbor trail boot added.';State semantics
ARIA does not replace behavior. If aria-disabled="true" keeps a busy button focusable, JavaScript must also block repeated activation.
role="status"Polite, non-interrupting success, result, and progress feedback that does not receive focus.
aria-busyIndicates that an element or region is being updated. Remove it when processing finishes.
aria-pressedAdding an item is an action, not a persistent on/off toggle. Do not invent toggle state.
Quick test