Order Summary
ProCart / checkout totals panel that renders the server quote verbatim and badges any locally-derived total as an estimate. Shipping / tax / discount rows, inclusive-tax mode, arbitrary extra lines, and content slots for a coupon field and checkout button. All arithmetic runs on integer minor units, so the visible rows always add up to the visible total.
Complexity tier: Interactive The primitive bar, plus declared async states, a keyboard model, focus restoration and undo for destructive actions.
import { SvOrderSummaryComponent } from '@styloviz-pro/commerce';Demo & usage
Basic usage
ProUsage example — open the gallery for the full interactive demo.
An interactive demo for this component lives in the gallery.
Open live demoMore examples
Server quote (authoritative)
ProRendered verbatim. A disagreement with the rows is shown, not hidden.
Re-pricing in flight
ProMarks the figure stale so nobody pays against a superseded total.
Inclusive tax (VAT / GST)
ProThe subtotal already contains the tax, so the tax line is shown but not added.
Pending shipping/tax
ProNull values read "Calculated at checkout".
Itemized adjustments, one line per label
ProA `tax` line follows `taxMode` — added when exclusive, shown and marked "(included)" when the subtotal already contains it. Repeated labels are expected: itemizing per item or per shipment is what produces them.
Acting on the gap between the two figures
ProThe panel always says how far apart they are and in which direction. `reconciliationDelta` is that number, signed and positive when the server charges more, so a host can hold the pay button rather than only show a notice.
With slots
ProWhen to use
- The totals panel on cart, every checkout step and the order confirmation.
- You have an authoritative total from a pricing or checkout API and want it rendered verbatim beside the rows that explain it.
- You only have client-side figures and want them honestly labelled as an estimate.
- You need to drop a coupon field or checkout button beside the totals.
Async states
None — this component has nothing to load, so it has no loading, empty or error state to drive.
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| heading | string | 'Order summary' | Panel heading. |
| subtotalrequired | number | — | Items subtotal. |
| itemCount | number | 0 | Number of items (shown next to the subtotal label). |
| shipping | number | null | null | Shipping cost. `null` shows the pending label; 0 shows the free label. |
| tax | number | null | null | Tax amount. `null` shows the pending label. |
| taxMode | TaxMode | 'exclusive' | Whether `tax` is added to the subtotal or already inside it. An `inclusive` tax is informational and is *not* added to the total. |
| discount | number | 0 | Discount as a positive number (subtracted from the total). |
| discountLabel | string | 'Discount' | Label for the discount line. |
| lines | readonly OrderSummaryLine[] | [] | Extra lines (fees, gift wrap, credit, …) inserted before the total. |
| quote | OrderSummaryQuote | null | null | The authoritative total from the server. When set, it is rendered verbatim and the panel's own arithmetic is used only to detect a divergence. See the note on the class. |
| quotePending | boolean | false | A fresh quote is in flight, so the figure on screen is already stale. Set this while re-pricing (an address change, a coupon being applied) so nobody confirms payment against a superseded total. |
| currency | string | 'USD' | ISO 4217 currency code. |
| locale | string | 'en-US' | BCP-47 locale. |
| minorUnits | boolean | false | Treat all amounts as minor units. |
| freeShippingLabel | string | 'Free' | Label used when shipping is 0. |
| pendingLabel | string | 'Calculated at checkout' | Text shown for a null shipping / tax value. |
| inclusiveTaxLabel | string | 'included' | Marks the tax row when `taxMode` is 'inclusive'. |
| estimateLabel | string | 'Estimate' | Badge on the Total row when the figure is derived locally. |
| updatingLabel | string | 'Updating…' | Badge on the Total row while `quotePending`. |
| repricedLabel | string | 'This total was confirmed by the server… | Notice when the server total differs from what the lines add up to. |
| repricedHigherLabel | string | 'more than the lines add up to' | Reads after the difference when the server total is the larger figure. |
| repricedLowerLabel | string | 'less than the lines add up to' | Reads after the difference when the server total is the smaller figure. |
| linesIncompleteLabel | string | 'This total includes charges that are s… | Notice when a quote arrived while a charge is still being calculated, so the rows on screen cannot sum to the authoritative total. |
| currencyMismatchLabel | string | 'This total is priced in a different cu… | Notice when the server priced in a different currency to this panel. |
| overDiscountedLabel | string | 'The discounts exceed the order value, … | Notice when discounts exceed everything they apply to. |
| overDiscountedQuotedLabel | string | 'The discounts exceed the value of the … | Notice when discounts exceed the lines *and* a server total is being shown. Nothing local was floored in that case, so the other label would describe a cap the customer is not looking at. |
| note | string | '' | Optional fine print under the total. |
| showSavings | boolean | true | Show the emphasised "You saved …" row when there is a saving. |
Customization & theming
- Discrete subtotal / shipping / tax / discount rows plus arbitrary extra lines, each with its own label, optional note and one of four kinds (`charge`, `discount`, `tax`, `muted`).
- Free-shipping, pending, estimate, updating and reconciliation-notice labels are all configurable — including the two direction words the repriced notice reads with (`repricedHigherLabel` / `repricedLowerLabel`) and the still-calculating notice (`linesIncompleteLabel`).
- Exclusive or inclusive tax mode, honoured by itemized `tax` lines as well as the built-in row.
- Content slots: `[svSummaryTop]` and `[svSummaryFooter]`.
- Any ISO currency + locale, with minor-unit support and the correct exponent per currency (JPY has none, KWD has three).
Best practices
- Do: Pass `[quote]` with the total your pricing API returned. The panel is not the source of truth for what a customer is charged, and a client total that disagrees with the charge is a chargeback, not a UI bug.
- Do: Set `[quotePending]` while a new quote is being fetched — after an address change or a coupon — so nobody confirms payment against a superseded figure.
- Do: Set `taxMode="inclusive"` in VAT / GST markets. The default adds the tax on top, which double-charges it when the subtotal already contains it.
- Do: Use `null` shipping/tax before they are known so the panel reads "Calculated at checkout" and the estimate is treated as incomplete rather than repriced.
- Don't: Don't treat the estimate as the amount to charge, and don't try to hide the "Estimate" badge — there is no input for it. Supply `[quote]`, which is the same act as making the claim true.
- Don't: Don't convert a quote into the panel's currency yourself to silence the mismatch notice. Pass the quote in the currency the server priced it in; the panel shows it in that currency deliberately.
- Tip: Give discounts the `discount` kind in `lines` so they subtract and render green. The savings row reports what was actually deducted, so an over-large coupon cannot claim more than the order was worth.
- Do: Give an itemized tax line `kind: 'tax'` rather than `charge`. Under `taxMode="inclusive"` a `charge` line is added on top of a subtotal that already contains it — the VAT gets charged twice — while a `tax` line is shown, marked "(included)" and left out of the total.
- Do: Read `reconciliationDelta` if a gap should do more than display: it is the signed difference in your own unit basis, positive when the server charges more, and zero whenever the two figures are not comparable — no quote, two currencies, or an estimate that is still partial (`estimateIsPartial()`, e.g. shipping not yet priced). Gate the pay button on it or log it.
- Don't: Don't use `muted` for a line you do not want charged. It changes how prominently the row reads, not the arithmetic — the amount is added in full. There is no kind that displays an amount without moving the money except `tax` under an inclusive mode.
Accessibility
- Rendered as a definition list with a labelled region, and the heading id is per-instance so a cart drawer and a checkout panel on one page are never announced with each other's name.
- Totals are tabular-nums text, not images.
- The estimate / updating badges are text, not colour alone.
- Reconciliation notices sit in a `role="status"` region so they reach a screen reader without a focus change — including the size and direction of any gap between the rows and the authoritative total.
- An inclusive tax line carries its "(included)" marker as text on the label, so a row that is deliberately not added never reads as an arithmetic error.
- Discount and free-shipping colours meet contrast in light and dark mode.
Feedback on Order Summary
Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.