Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

Tutorials

Customize order summary lines

The Cart drop-in’s OrderSummary container renders a fixed set of lines by default, such as subtotal, discounts, and tax. This tutorial shows you how to customize those lines: reorder, remove, or add your own, using the updateLineItems prop.

  • Edit the OrderSummary container
  • Edit the updateLineItems prop
  • Edit the OrderSummaryLine container

By the end of this tutorial, you’ll have:

  • Order summary lines customized through the updateLineItems prop on the OrderSummary container — reordering, removing, or adding lines like the fixed product tax (FPT) example.
  • Subtotal and tax lines grouped into a collapsible section using the Storefront SDK’s Accordion component.
  • A new order summary line rendered with the OrderSummaryLine container, showing a custom label and price.

Customize the lines of the Order Summary to meet your needs

Section titled “Customize the lines of the Order Summary to meet your needs”

This customization is possible thanks to the attribute updateLineItems from the OrderSummary container. This attribute allows you to modify the order summary lines before they are rendered.

export const OrderSummary: Container<OrderSummaryProps, CartModel | null> = ({
...
updateLineItems = (lineItems) => lineItems,
...
});

It doesn’t matter if you want to customize the existing order summary lines, add new ones, or skip some of them. The OrderSummary container passes the updateLineItems to the OrderSummary component, which performs the appropriate actions.

updateLineItems is an optional function that receives the line items as an argument and returns the updated line items. In both cases, lineItems are an array of OrderSummaryLineItem object.

export interface OrderSummaryLineItem {
key: string;
title?: string;
className?: string;
sortOrder: number;
content:
| string
| JSXInternal.Element
| VNode<HTMLAttributes<HTMLDivElement>>
| OrderSummaryLineItem[]
| undefined;
}

There are default order summary lines in the OrderSummary component (including several not shown here, such as shipping and gift wrapping). If no customization is needed, and therefore nothing is passed using the updateLineItems attribute, the default order summary lines will be rendered. Let’s imagine that lineItems contains the following subset of those lines:

const lineItems: Array<OrderSummaryLineItem> = [
{
key: 'subTotalContent',
sortOrder: 100,
content: subTotalContent,
},
{
key: 'discountsContent',
sortOrder: 600,
content: discountsContent,
},
{
key: 'taxContent',
sortOrder: 800,
content: taxContent,
},
];

In the example above, the OrderSummary component renders the sub-total, discounts, and tax lines, in that order. The value of the sortOrder attribute determines the order in which the lines are rendered. The larger the sortOrder value, the lower the line will be rendered in the order summary.

The content attribute can be a string, a JSX element, or an array of OrderSummaryLineItem objects (whenever is not undefined). For instance, you could choose to render a JSX element in a form of a OrderSummaryLine container. This OrderSummaryLine container it is defined as follows:

export interface OrderSummaryLineProps extends HTMLAttributes<HTMLDivElement> {
label: VNode | string;
price: VNode<HTMLAttributes<HTMLSpanElement>>;
classSuffixes?: Array<string>;
labelClassSuffix?: string;
testId?: string;
children?: any;
}

See an example of how to use the OrderSummaryLine container below, where only the mandatory props are passed:

<OrderSummaryLine
label={translations.subtotalLabel}
price={subTotal.price}
classSuffixes={['subTotal']}
>
{children}
</OrderSummaryLine>
);

Note that the OrderSummaryLine container behaves like a wrapper for the OrderSummaryLine component. The component ultimately decides how to render the line item based on the children attribute.

export interface OrderSummaryLineComponentProps
extends HTMLAttributes<HTMLDivElement> {
label: VNode | string;
price: VNode<HTMLAttributes<HTMLSpanElement>>;
classSuffixes?: Array<string>;
labelClassSuffix?: string;
testId?: string;
children?: any;
}

To customize the order summary lines, you need to render the Cart component passing the OrderSummary component as a slot. When rendering the OrderSummary component, you can pass the updateLineItems attribute to customize the order summary lines as needed.

// Cart
provider.render(Cart, {
slots: {
OrderSummary: (ctx) => {
const orderSummary = document.createElement('div');
provider.render(OrderSummary, {
updateLineItems: (lineItems) => {
// Customize the order summary lines here
return lineItems;
}
}
}
}
});

For the examples shown below, assume that this is how Order Summary looks originally:

Cart without any customization

Cart without any customization

The following example removes the Total saved line:

updateLineItems: (lineItems) => {
const index = lineItems.map(item => item.key).indexOf('totalSavedContent');
lineItems.splice(index, 1);
return lineItems;
}

Cart after removing Total Saved line

Cart after removing Total Saved line

Reorder items: Move primary action to the beginning

Section titled “Reorder items: Move primary action to the beginning”

The following example moves the Checkout button to the top:

updateLineItems: (lineItems) => {
lineItems.map(lineItem => {
if (lineItem.key === 'primaryActionContent') {
lineItem.sortOrder = 50;
}
return lineItem;
});
return lineItems;
};

Cart after moving primary action to the beginning

Cart after moving primary action to the beginning

Group items: Group subtotal and tax in an accordion

Section titled “Group items: Group subtotal and tax in an accordion”

You can group and sort order summary lines into sections using the Accordion component from the Storefront SDK (Elsie) . For the full set of UI primitives, see the Storefront SDK components overview .

The following example groups the subtotal and tax in an accordion:

updateLineItems: (lineItems) => {
const totalsIndex = lineItems.map(item => item.key).indexOf('taxContent');
const taxContent = lineItems.splice(totalsIndex, 1)[0];
const subtotalIndex = lineItems.map(item => item.key).indexOf('subTotalContent');
const subTotalContent = lineItems.splice(subtotalIndex, 1)[0];
lineItems.push({
key: 'subtotalTaxGrouped',
sortOrder: 50,
title: 'Subtotal and Tax',
content: [
taxContent,
subTotalContent,
],
});
return lineItems;
}

Cart after grouping subtotal and tax in an accordion

Cart after grouping subtotal and tax in an accordion

The following example adds the FPT line:

updateLineItems: (lineItems) => {
const totalFpt = ctx.data.items.reduce((allItemsFpt, item) => {
const itemFpt = item.fixedProductTaxes.reduce((accumulator, fpt) => {
accumulator.labels.push(fpt.label);
accumulator.total += fpt.amount.value;
return accumulator;
}, {
labels: [],
total: 0
});
allItemsFpt.labels = [...allItemsFpt.labels, ...itemFpt.labels];
allItemsFpt.total += itemFpt.total;
return allItemsFpt;
}, {
labels: [],
total: 0
});
lineItems.push({
key: 'fpt',
sortOrder: 350,
title: 'Fixed Product Tax',
content: OrderSummaryLine({label: "FPT(" + totalFpt.labels.join(',') + ')', price: Price({amount: totalFpt.total}), classSuffix: 'fpt'})
})
return lineItems;
};

Cart after adding a new order summary line

Cart after adding a new order summary line