Order summary
The last step of agentic checkout: every line, charge and address in tabular figures, then a purchase that cannot happen by accident. Hold to pay, or press once to arm and once to confirm, with processing, placed and failed states.
On this page
Line items, free shipping, tax and the total in tabular figures. Hold the button until the bar fills to place the order.
Installation
Usage
import { OrderSummary } from "@/components/ui/chatcn/order-summary"
<OrderSummary
merchant="Fieldhouse Running"
items={cart.items}
shipping={0}
tax={cart.tax}
currency="EUR"
payment={{ brand: "Visa", last4: "4242" }}
shippingAddress={{ name: "Rosa Delgado", lines: ["Rua da Rosa 112", "1200-389 Lisboa"] }}
onConfirm={async () => ({ orderNumber: (await checkout.complete(cart.id)).number })}
/>subtotal and total are worked out from the items when you leave them out. Resolve onConfirm with the order number for the receipt; throw an Error and its message becomes the failed state's instructions. Without a message, the card says nothing was charged and to try again or use another card.
A deliberate confirm
hold(default): press and hold forholdMs(1200). A filled layer wipes across the label, linear, so the progress is honest. Letting go early snaps back. Space and Enter can be held too.step: Place order arms a Confirm and pay button that names the amount. A double click cannot confirm, and the step disarms after 8 s.- While
streamingthe order is still being assembled, and nothing can be paid.
Examples
Confirm step, compact
Items fold behind a count. Place order arms a second Confirm and pay button, and the bank declines.
States
Loading, still assembling, processing, placed with an order number, failed and empty.
Props
| Prop | Type | Notes |
|---|---|---|
items | { id, title, quantity, unitPrice, detail?, image? }[] | Empty shows Your cart is empty |
subtotal, total | number | Computed when left out |
shipping, shippingLabel | number, string | 0 reads Free |
tax, discount | number, { label, amount } | |
currency, locale | string | |
payment | { brand, last4, expiry? } | Brand as text |
shippingAddress | { name, lines } | |
onChangePayment, onChangeAddress | () => void | Show Change links |
confirmMode, holdMs | "hold" | "step", number | Default hold, 1200 ms |
onConfirm | () => Promise<{ orderNumber? }> | Reject to fail |
onCancel | () => void | Shows Cancel order |
status, orderNumber, error | OrderStatus | review, processing, success, failed |
receiptNote | ReactNode | After success |
layout | "full" | "compact" | compact folds the items behind a count |
loading, streaming | boolean | |
labels | Partial<OrderSummaryLabels> | Every string the summary shows or announces, for translation. Totals, counts and names arrive as function arguments |
Keyboard
| Key | Action |
|---|---|
Space or Enter, held | Hold to pay. Releasing early cancels |
Enter | Place order, then Confirm and pay (step mode) |
Tab | Change links, the confirm button, Cancel order |
Accessibility
- The hold button says how long to hold. Processing and the armed step are announced through a polite status region; a failure is an alert.
- Totals are a description list in tabular figures, so columns of money line up.
- Placed is green with a check, failed is red with an alert icon, and both say it in words.
Motion
- The hold fill animates
clip-path, linear overholdMs, and returns in 200 ms. It stays under reduced motion because it is the progress itself. - The status icon swaps in with the 150 ms blur crossfade. Items fold by height in 200 ms in the compact layout.