Skip to content

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

Cart slots

Learn about the slots provided in the Cart drop-in component.

Extending drop-in components describes default properties available to all slots.

CartSummaryList slots

The slots for the CartSummaryList container allow you to customize the appearance of the cart summary list.

interface CartSummaryListProps
slots?: {
Heading?: SlotProps;
EmptyCart?: SlotProps;
Footer?: SlotProps;
Thumbnail?: SlotProps<{
item: CartModel['items'][number];
defaultImageProps: ImageProps;
}>;
ProductAttributes?: SlotProps;
CartSummaryFooter?: SlotProps;
CartItem?: SlotProps;
UndoBanner?: SlotProps<{
item: CartModel['items'][0];
loading: boolean;
error?: string;
onUndo: () => void;
onDismiss: () => void;
}>;
ItemTitle?: SlotProps<{ item: CartModel['items'][number] }>;
ItemPrice?: SlotProps<{ item: CartModel['items'][number] }>;
ItemQuantity?: SlotProps<{
item: CartModel['items'][number];
enableUpdateItemQuantity: boolean;
handleItemQuantityUpdate: (
item: CartModel['items'][number],
quantity: number
) => void;
itemsLoading: Set<string>;
handleItemsError: (uid: string, message?: string) => void;
handleItemsLoading: (uid: string, state: boolean) => void;
onItemUpdate?: ({ item }: { item: CartModel['items'][number] }) => void;
}>;
ItemTotal?: SlotProps<{ item: CartModel['items'][number] }>;
ItemSku?: SlotProps<{ item: CartModel['items'][number] }>;
ItemRemoveAction?: SlotProps<{
item: CartModel['items'][number];
enableRemoveItem: boolean;
handleItemQuantityUpdate: (
item: CartModel['items'][number],
quantity: number
) => void;
handleItemsError: (uid: string, message?: string) => void;
handleItemsLoading: (uid: string, state: boolean) => void;
onItemUpdate?: ({ item }: { item: CartModel['items'][number] }) => void;
itemsLoading: Set<string>;
}>;
};

Heading slot

The Heading slot allows you to add content to the top of the CartSummaryList container.

provider.render(CartSummaryList, {
slots: {
Heading: (ctx) => {
// Runs on mount
const heading = document.createElement('h2');
heading.innerText = 'Cart List';
ctx.appendChild(heading);
},
},
})($list),

EmptyCart slot

The EmptyCart slot allows you to add content to the CartSummaryList container when the cart is empty.

provider.render(CartSummaryList, {
slots: {
EmptyCart: (ctx) => {
// Runs on mount
const emptyCart = document.createElement('div');
emptyCart.innerText = 'Your cart is empty';
ctx.appendChild(emptyCart);
},
},
})($list),

Thumbnail slot

Define a callback function in the Thumbnail slot of the CartSummaryList container to modify or replace the thumbnail section for each item in the cart.

The context object passed to the callback function includes an item property that contains the item data with the following type:

export interface Item {
taxedPrice: {
value: number;
currency: string;
};
rowTotal: {
value: number;
currency: string;
};
rowTotalIncludingTax: {
value: number;
currency: string;
};
itemType: string;
uid: string;
url: {
urlKey: string;
categories: string[];
};
quantity: number;
sku: string;
name: string;
image: {
src: string;
alt: string;
};
links?: {
count: number;
result: string;
};
price: {
value: number;
currency: string;
};
total: {
value: number;
currency: string;
};
discountedTotal?: {
value: number;
currency: string;
};
discount?: {
value: number;
currency: string;
};
regularPrice: {
value: number;
currency: string;
};
discounted: boolean;
bundleOptions?: { [key: string]: any };
selectedOptions?: { [key: string]: any };
customizableOptions?: { [key: string]: any };
message?: string;
recipient?: string;
recipientEmail?: string;
sender?: string;
senderEmail?: string;
lowInventory?: boolean;
insufficientQuantity?: boolean;
onlyXLeftInStock?: number | null;
outOfStock?: boolean;
notAvailableMessage?: string;
stockLevel?: string;
productAttributes?: Array<{
code: string;
value?: string;
selected_options?: {
value: string;
label: string;
}[];
}>;
}

Example extension

The following example demonstrates how to extend the Thumbnail slot.

return provider.render(CartSummaryList, {
hideHeading: hideHeading === 'true',
routeProduct: (product) => `/products/${product.url.urlKey}/${product.sku}`,
routeEmptyCartCTA: startShoppingURL ? () => startShoppingURL : undefined,
maxItems: parseInt(maxItems, 10) || undefined,
attributesToHide: hideAttributes.split(',').map((attr) => attr.trim().toLowerCase()),
enableUpdateItemQuantity: enableUpdateItemQuantity === 'true',
enableRemoveItem: enableRemoveItem === 'true',
slots: {
Thumbnail: (ctx) => {
const { item } = ctx;
// Create a link to save the item for later
const saveForLaterLink = document.createElement('a');
saveForLaterLink.href = '#';
saveForLaterLink.addEventListener('click', (e) => {
e.preventDefault();
console.log(`Saving ${item.name}(${item.sku}) for later`);
// TODO: Implement save for later functionality
});
saveForLaterLink.innerText = 'Save for later';
// Create a separator
const separator = document.createElement('span');
separator.innerText = ' | ';
// Create a link to remove the item from the cart
const removeLink = document.createElement('a');
removeLink.href = '#';
removeLink.addEventListener('click', (e) => {
e.preventDefault();
console.log(`Removing ${item.name}(${item.sku}) from cart`);
// TODO: Implement remove item functionality
});
removeLink.innerText = 'Remove';
// Create a container to hold the links
const container = document.createElement('div');
container.innerHTML = '<div class="cart-summary__thumbnail"/>';
// Style the container
container.style.font = 'var(--type-details-caption-2-font)'
container.style.display = 'flex';
container.style.justifyContent = 'space-between';
// Append the links to the container
container.appendChild(saveForLaterLink);
container.appendChild(separator);
container.appendChild(removeLink);
// Append the container as a child to the existing thumbnail content
ctx.appendChild(container)
}
}
})(block);

The Footer slot allows you to add content to the bottom of the CartSummaryList container.

The following example demonstrates how to extend the Footer slot by adding a promotional cart rule to each product in the cart.

Footer: (ctx) => {
// Runs on mount
const wrapper = document.createElement('div');
ctx.appendChild(wrapper);
// Append Product Promotions on every update
ctx.onChange((next) => {
wrapper.innerHTML = '';
next.item?.discount?.label?.forEach((label) => {
const discount = document.createElement('div');
discount.style.color = '#3d3d3d';
discount.innerText = label;
wrapper.appendChild(discount);
});
});
},

ProductAttributes slot

The ProductAttributes slot allows you to add custom content to the CartSummaryList container.

The following example demonstrates how to add the Fashion Material and Fashion Style product attributes to each product in the cart.

return provider.render(CartSummaryList, {
enableRemoveItem: true,
enableUpdateItemQuantity: true,
routeProduct: (item) => {
return `${item.url.categories.join('/')}/${item.url.urlKey}`;
},
routeEmptyCartCTA: () => '#empty-cart',
slots: {
ProductAttributes: (ctx) => {
// Prepend Product Attributes
const ProductAttributes = ctx.item?.productAttributes;
ProductAttributes?.forEach((attr) => {
if(attr.code === "Fashion Material" || attr.code === "Fashion Style") {
if(attr.selected_options) {
const selectedOptions = attr.selected_options
.filter((option) => option.label.trim() !== '')
.map((option) => option.label)
.join(', ');
if(selectedOptions) {
const productAttribute = document.createElement('div');
productAttribute.innerText = `${attr.code}: ${selectedOptions}`;
ctx.appendChild(productAttribute);
}
} else if (attr.value) {
const productAttribute = document.createElement('div');
productAttribute.innerText = `${attr.code}: ${attr.value}`;
ctx.appendChild(productAttribute);
}
}
})
},
},
})(productList);

CartSummaryFooter slot

The CartSummaryFooter slot allows you to add content to the bottom of the CartSummaryList container.

provider.render(CartSummaryList, {
slots: {
CartSummaryFooter: (ctx) => {
const cartSummaryFooter = document.createElement('div');
cartSummaryFooter.innerText = 'Cart summary footer';
ctx.appendChild(cartSummaryFooter);
},
},
})($list),

ItemTitle slot

The ItemTitle slot allows you to customize the title display for each item in the CartSummaryList container.

The following example demonstrates how to replace the default title with a custom title:

provider.render(CartSummaryList, {
enableRemoveItem: true,
enableUpdateItemQuantity: true,
slots: {
ItemTitle: (ctx) => {
// Create custom title element
const customTitle = document.createElement('div');
customTitle.className = 'cart-item-custom-title';
customTitle.textContent = 'Custom Title';
ctx.replaceWith(customTitle);
},
},
})(cartSummaryList);

ItemPrice slot

The ItemPrice slot allows you to customize the price display for each item in the CartSummaryList container.

The following example demonstrates how to add a custom price label:

provider.render(CartSummaryList, {
enableRemoveItem: true,
enableUpdateItemQuantity: true,
slots: {
ItemPrice: (ctx) => {
const priceLabel = document.createElement('span');
priceLabel.className = 'cart-item-price-label';
priceLabel.textContent = 'Item Price';
ctx.prependChild(priceLabel);
},
},
})(cartSummaryList);

ItemQuantity slot

The ItemQuantity slot allows you to customize the quantity display and controls for each item in the CartSummaryList container.

The following example demonstrates how to customize the quantity field by adding a “Qty:” label and using an input component from the SDK:

import {
provider as UI,
Input,
} from '@dropins/tools/components.js';
provider.render(CartSummaryList, {
enableRemoveItem: true,
enableUpdateItemQuantity: true,
slots: {
ItemQuantity: (ctx) => {
const { item, handleItemQuantityUpdate } = ctx;
// Create container with label and input
const quantityContainer = document.createElement('div');
quantityContainer.className = 'cart-item-quantity-container';
// Add "Qty:" label
const quantityLabel = document.createElement('span');
quantityLabel.className = 'cart-item-quantity-label';
quantityLabel.textContent = 'Qty:';
// Create input wrapper for SDK Input component
const inputWrapper = document.createElement('div');
inputWrapper.className = 'cart-item-quantity-input';
inputWrapper.style.display = 'inline-block';
inputWrapper.style.width = '60px';
// Render SDK Input component
UI.render(Input, {
value: item.quantity.toString(),
min: 1,
size: 'small',
variant: 'primary',
onValue: (value) => {
const newQuantity = parseInt(value, 10);
if (
!Number.isNaN(newQuantity)
&& newQuantity > 0
&& newQuantity !== item.quantity
) {
handleItemQuantityUpdate(item, newQuantity);
}
},
})(inputWrapper);
// Style the container for inline layout
quantityContainer.style.display = 'flex';
quantityContainer.style.alignItems = 'center';
quantityContainer.style.gap = 'var(--spacing-xsmall)';
quantityContainer.appendChild(quantityLabel);
quantityContainer.appendChild(inputWrapper);
ctx.replaceWith(quantityContainer);
},
},
})(cartSummaryList);

ItemTotal slot

The ItemTotal slot allows you to customize the total price display for each item in the CartSummaryList container.

The following example demonstrates how to add a custom total label:

provider.render(CartSummaryList, {
enableRemoveItem: true,
enableUpdateItemQuantity: true,
slots: {
ItemTotal: (ctx) => {
const totalLabel = document.createElement('div');
totalLabel.className = 'cart-item-total-label';
totalLabel.textContent = 'Item Total';
ctx.prependChild(totalLabel);
},
},
})(cartSummaryList);

ItemSku slot

The ItemSku slot allows you to customize the SKU display for each item in the CartSummaryList container.

The following example demonstrates how to replace the default SKU with a custom SKU:

provider.render(CartSummaryList, {
enableRemoveItem: true,
enableUpdateItemQuantity: true,
slots: {
ItemSku: (ctx) => {
const customSku = document.createElement('div');
customSku.className = 'cart-item-custom-sku';
customSku.textContent = 'custome-sku';
ctx.replaceWith(customSku);
},
},
})(cartSummaryList);

ItemRemoveAction slot

The ItemRemoveAction slot allows you to customize the remove action button for each item in the CartSummaryList container.

The following example demonstrates how to replace the default remove button with a custom button:

provider.render(CartSummaryList, {
enableRemoveItem: true,
enableUpdateItemQuantity: true,
slots: {
ItemRemoveAction: (ctx) => {
// Simple remove button with text
const removeButton = document.createElement('button');
removeButton.innerText = 'Remove';
// apply styling using design tokens where possible
removeButton.style.background = 'transparent';
removeButton.style.border = 'none';
removeButton.style.color = 'var(--color-neutral-600)';
removeButton.style.cursor = 'pointer';
removeButton.style.fontSize = 'var(--type-body-2-font-size)';
removeButton.style.padding = '0';
removeButton.style.paddingRight = 'var(--spacing-medium)';
removeButton.style.fontWeight = 'var(--type-body-2-font-weight, normal)';
removeButton.style.textDecoration = 'underline';
removeButton.style.float = 'right';
removeButton.style.marginLeft = 'auto';
removeButton.style.display = 'block';
// Remove functionality
removeButton.addEventListener('click', () => {
if (ctx.handleItemQuantityUpdate) {
ctx.handleItemQuantityUpdate(ctx.item, 0);
}
});
ctx.replaceWith(removeButton);
},
},
})(cartSummaryList);

OrderSummary slots

The OrderSummaryProps interface defines two slots for customizing the appearance of the order summary.

interface OrderSummaryProps
slots?: {
EstimateShipping?: SlotProps;
Coupons?: SlotProps;
};

EstimateShipping slot

The EstimateShipping slot allows you to add estimated shipping information to the OrderSummary container.

The following example demonstrates how to add the Estimate Shipping layout to the OrderSummary container.

return provider.render(OrderSummary, {
routeCheckout: () => '#checkout',
errors: ctx.hasErrors,
slots: {
EstimateShipping: (ctx) => {
const estimateShippingForm = document.createElement('div');
provider.render(EstimateShipping)(estimateShippingForm);
ctx.appendChild(estimateShippingForm);
}
},
})(orderSummary);

Coupons slot

The Coupons slot allows you to add the Coupons layout to the OrderSummary container.

The following example demonstrates how to enable coupons to the OrderSummary container.

return provider.render(OrderSummary, {
routeCheckout: () => '#checkout',
errors: ctx.hasErrors,
slots: {
Coupons: (ctx) => {
const coupons = document.createElement('div');
provider.render(Coupons)(coupons);
ctx.appendChild(coupons);
}
},
})(orderSummary);

MiniCart slot

The MiniCartProps interface defines slots for customizing the appearance of the mini cart.

interface MiniCartProps
slots?: {
ProductList?: SlotProps;
ProductListFooter?: SlotProps;
PreCheckoutSection?: SlotProps;
Thumbnail?: SlotProps<{
item: CartModel['items'][number];
defaultImageProps: ImageProps;
}>;
Heading?: SlotProps;
EmptyCart?: SlotProps;
Footer?: SlotProps;
ProductAttributes?: SlotProps;
CartSummaryFooter?: SlotProps;
CartItem?: SlotProps;
UndoBanner?: SlotProps<{
item: CartModel['items'][0];
loading: boolean;
error?: string;
onUndo: () => void;
onDismiss: () => void;
}>;
ItemTitle?: SlotProps<{ item: CartModel['items'][number] }>;
ItemPrice?: SlotProps<{ item: CartModel['items'][number] }>;
ItemQuantity?: SlotProps<{
item: CartModel['items'][number];
enableUpdateItemQuantity: boolean;
handleItemQuantityUpdate: (
item: CartModel['items'][number],
quantity: number
) => void;
itemsLoading: Set<string>;
handleItemsError: (uid: string, message?: string) => void;
handleItemsLoading: (uid: string, state: boolean) => void;
onItemUpdate?: ({ item }: { item: CartModel['items'][number] }) => void;
}>;
ItemTotal?: SlotProps<{ item: CartModel['items'][number] }>;
ItemSku?: SlotProps<{ item: CartModel['items'][number] }>;
ItemRemoveAction?: SlotProps<{
item: CartModel['items'][number];
enableRemoveItem: boolean;
handleItemQuantityUpdate: (
item: CartModel['items'][number],
quantity: number
) => void;
handleItemsError: (uid: string, message?: string) => void;
handleItemsLoading: (uid: string, state: boolean) => void;
onItemUpdate?: ({ item }: { item: CartModel['items'][number] }) => void;
itemsLoading: Set<string>;
}>;
};

Note: Many slots are shared between MiniCart and CartSummaryList components. For implementation details of shared slots, refer to the corresponding examples in the CartSummaryList slots section above.

The following slots are specific to the MiniCart component:

ProductListFooter slot

The ProductListFooter slot allows you to add content after the product list and before the subtotal section of the MiniCart container.

The following example demonstrates how to extend the ProductListFooter by adding the store return policy.

return provider.render(MiniCart, {
routeEmptyCartCTA: () => '#empty-cart',
routeCart: () => '#cart',
routeCheckout: () => '#checkout',
slots: {
ProductListFooter: (ctx) => {
const productListFooter = document.createElement('div');
ctx.appendChild(productListFooter);
ctx.onChange((next) => {
// Clear the existing content
productListFooter.innerHTML = '';
if (Object.keys(next.data.items).length === 0) {
return;
}
const shadowWrapper = document.createElement('div');
shadowWrapper.style.backgroundColor = '#EFF5EF';
shadowWrapper.style.borderRadius = '5px';
// Create the content div
const contentDiv = document.createElement('div');
contentDiv.innerHTML = "<p style='line-height: 1.5;'>Enjoy hassle-free shopping with our 30-day return policy!</p>";
contentDiv.style.display = 'flex';
contentDiv.style.flexDirection = 'column';
contentDiv.style.padding = '12px';
// Append the content div to the shadow wrapper
shadowWrapper.appendChild(contentDiv);
productListFooter.appendChild(shadowWrapper);
});
},
},
})(orderSummary);

PreCheckoutSection slot

The PreCheckoutSection slot allows you to add content after the the subtotal section and before the Call to Action buttons of the MiniCart container.

The following example demonstrates how to extend the PreCheckoutSection by adding the loyalty program callouts.

return provider.render(MiniCart, {
routeEmptyCartCTA: () => '#empty-cart',
routeCart: () => '#cart',
routeCheckout: () => '#checkout',
slots: {
PreCheckoutSection: (ctx) => {
const preCheckoutSection = document.createElement('div');
ctx.appendChild(preCheckoutSection);
ctx.onChange((next) => {
// Clear the existing content
preCheckoutSection.innerHTML = '';
if (Object.keys(next.data.items).length === 0) {
return;
}
// Create a wrapper div for the shadow background
const shadowWrapper = document.createElement('div');
shadowWrapper.style.backgroundColor = '#EEEFFB';
shadowWrapper.style.borderRadius = '5px';
// Create the content div
const contentDiv = document.createElement('div');
contentDiv.innerHTML = "<p style='line-height: 1.5;'>Earn rewards every time you shop! Sign up for our free loyalty program today and start earning points on this purchase.</p>";
contentDiv.style.display = 'flex';
contentDiv.style.flexDirection = 'column';
contentDiv.style.padding = '12px';
// Append the content div to the shadow wrapper
shadowWrapper.appendChild(contentDiv);
// Append the shadow wrapper to the preCheckoutSection div
preCheckoutSection.appendChild(shadowWrapper);
});
},
},
})(orderSummary);