Skip to main content

CartTotalSummary

Description

A headless render props component that provides cart summary data including subtotal, discount, shipping, tax, and grand total. When no children function is provided, it renders a DefaultCartSummary with Area-based extension points. When children is provided, it acts as a pure headless component.

Role in Theming

CartTotalSummary is one of EverShop's headless components — it owns the data extraction and tax-aware price formatting while leaving UI decisions to its parent:

  • With no children, CartTotalSummary renders a default summary layout with Areas (cartSummaryBeforeSubTotal, cartSummaryAfterSubTotal, etc.) that extensions can inject into.
  • With children, it renders nothing of its own — only what the children function returns.
  • Theme developers override the parent components that use CartTotalSummary (ShoppingCart, Checkout) to change the summary layout.
  • The data logic stays stable across themes. Tax-inclusive/exclusive price selection, loading state derivation, and cart data extraction are encapsulated.

Theme Override Points

CartTotalSummary is consumed by these components, which are the actual override targets for theme developers:

Parent ComponentRouteOverride Path in Theme
ShoppingCartcartthemes/<name>/src/pages/cart/ShoppingCart.tsx
Checkoutcheckoutthemes/<name>/src/pages/checkout/Checkout.tsx

Import

import {
CartTotalSummary,
DefaultCartSummary,
Subtotal,
Discount,
Shipping,
Tax,
Total
} from '@components/frontStore/cart/CartTotalSummary';

Usage

With Default Renderer

When no children are provided, it renders the built-in summary layout:

import { CartTotalSummary } from '@components/frontStore/cart/CartTotalSummary';

function CartSummary() {
return <CartTotalSummary />;
}

As Headless Component

Pass a children function to take full control of the rendering:

import { CartTotalSummary } from '@components/frontStore/cart/CartTotalSummary';

function CustomCartSummary() {
return (
<CartTotalSummary>
{({ subTotal, total, loading, taxAmount, showPriceIncludingTax }) => (
<div className="my-summary">
<div>Subtotal: {subTotal}</div>
{!showPriceIncludingTax && <div>Tax: {taxAmount}</div>}
<div>Total: {total}</div>
</div>
)}
</CartTotalSummary>
);
}

Props

NameTypeRequiredDescription
childrenRenderFunctionNoOptional render function. If omitted, DefaultCartSummary is used.

Render Function Props

When children is provided, the render function receives:

NameTypeDescription
loadingbooleanTrue when any cart operation is in progress
showPriceIncludingTaxbooleanWhether prices include tax (from store config)
noShippingRequiredbooleanTrue when cart has no shippable items
subTotalstringFormatted subtotal (tax-inclusive or exclusive based on config)
discountAmountstringFormatted discount amount
couponstring | undefinedApplied coupon code, if any
shippingMethodstring | undefinedSelected shipping method name
shippingCoststring | undefinedFormatted shipping cost
taxAmountstringFormatted total tax amount
totalstringFormatted grand total

Exported Sub-Components

CartTotalSummary also exports individual summary row components used by DefaultCartSummary. Theme developers can import and compose these individually:

ComponentPropsDescription
SubtotalsubTotal, loadingSubtotal row
DiscountdiscountAmount, coupon, loadingDiscount row with coupon form/remove
Shippingmethod, cost, noShippingRequired, loadingShipping method and cost row
TaxshowPriceIncludingTax, amount, loadingTax row (hidden when prices include tax)
Totaltotal, totalTaxAmount, priceIncludingTax, loadingGrand total row

Examples

Custom Summary Layout

import { CartTotalSummary } from '@components/frontStore/cart/CartTotalSummary';

function MinimalSummary() {
return (
<CartTotalSummary>
{({ subTotal, total, coupon, discountAmount, loading }) => (
<div className="summary">
<div className="row">
<span>Subtotal</span>
<span>{subTotal}</span>
</div>
{coupon && (
<div className="row discount">
<span>Discount ({coupon})</span>
<span>{discountAmount}</span>
</div>
)}
<div className="row total">
<span>Total</span>
<span>{loading ? '...' : total}</span>
</div>
</div>
)}
</CartTotalSummary>
);
}

Theme Override Example

A theme developer overrides the cart page summary. Create this file in your theme:

themes/my-theme/src/pages/cart/ShoppingCart.tsx

import { CartTotalSummary } from '@components/frontStore/cart/CartTotalSummary';
import { CartItems } from '@components/frontStore/cart/CartItems';

function ShoppingCart() {
return (
<div className="my-theme-cart">
<CartItems>
{({ items, isEmpty, onRemoveItem }) => (
/* Custom cart items layout */
<div>{/* ... */}</div>
)}
</CartItems>

<CartTotalSummary>
{({
subTotal,
total,
taxAmount,
shippingMethod,
shippingCost,
showPriceIncludingTax,
noShippingRequired,
loading
}) => (
<div className="my-theme-summary">
<div>Subtotal: {subTotal}</div>
{shippingMethod && !noShippingRequired && (
<div>Shipping ({shippingMethod}): {shippingCost}</div>
)}
{!showPriceIncludingTax && <div>Tax: {taxAmount}</div>}
<div className="grand-total">
Total: {loading ? 'Calculating...' : total}
</div>
</div>
)}
</CartTotalSummary>
</div>
);
}

export default ShoppingCart;

export const layout = {
areaId: 'content',
sortOrder: 10
};

Default Cart Summary Areas

When using CartTotalSummary without children, the DefaultCartSummary renders with these Area extension points (in order):

  1. cartSummaryBeforeSubTotal
  2. cartSummaryAfterSubTotal
  3. cartSummaryBeforeDiscount
  4. cartSummaryAfterDiscount
  5. cartSummaryBeforeShipping
  6. cartSummaryAfterShipping
  7. cartSummaryBeforeTax
  8. cartSummaryAfterTax
  9. cartSummaryBeforeTotal
  10. cartSummaryAfterTotal

Extensions can inject components into these areas without overriding the entire summary.

Features

  • Headless or Default: Works as headless (with children) or renders a default layout (without children)
  • Tax-Aware: Automatically selects tax-inclusive or exclusive prices based on store config
  • Loading State: Derives loading from all cart operation states
  • Area Extension Points: Default renderer includes Areas for extension injection
  • Composable Sub-Components: Individual row components can be imported and reused
  • Type Safe: Full TypeScript support


Support us


EverShop is an open-source project that relies on community support. If you find our project useful, please consider sponsoring us.