Skip to content

Order Summary Lines

The Cart dropin allows you to customize the lines of the Order Summary to meet your requirements.

You might want to group and sort the order summary lines into sections using the native Accordion component from Elsie.

You can specify the line items shown in the accordion and decide the order in which they are displayed. You can also customize the title and content of these order summary lines.

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. 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 lines:

const lineItems: Array<OrderSummaryLineItem> = [
{
key: 'subTotalContent',
sortOrder: 100,
content: subTotalContent,
},
{
key: 'discountsContent',
sortOrder: 300,
content: discountsContent,
},
{
key: 'taxContent',
sortOrder: 400,
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: 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: string;
price: VNode<HTMLAttributes<HTMLSpanElement>>;
classSuffixes?: Array<string>;
labelClassSuffix?: string;
testId?: string;
children?: any;
}

Where to perform the customizations

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;
}
}
}
}
});

Examples

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

Cart without any customization

Cart without any customization

Remove Item: Remove total saved

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

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

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

Add item: Add a new order summary line

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