Skip to content

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

Checkout Slots

The Checkout drop-in exposes slots for customizing specific UI sections. Use slots to replace or extend container components. For default properties available to all slots, see Extending drop-in components.

Version: 3.2.0
ContainerSlots
LoginFormHeading, Preferences, Title
PaymentMethodsMethods, Title
PlaceOrderContent
ShippingMethodsShippingMethodItem, Title
TermsAndConditionsAgreements

The slots for the LoginForm container allow you to customize its appearance and behavior.

interface LoginFormProps {
slots?: {
Heading?: SlotProps<{
authenticated: boolean;
}>;
Preferences?: SlotProps<{
email: string;
isEmailValid: boolean;
isAuthenticated: boolean;
}>;
Title?: SlotProps<Record<string, never>>;
};
}

The Heading slot allows you to customize the heading section of the LoginForm container.

import { render as provider } from '@dropins/storefront-checkout/render.js';
import { LoginForm } from '@dropins/storefront-checkout/containers/LoginForm.js';
await provider.render(LoginForm, {
slots: {
Heading: (ctx) => {
// Your custom implementation
const element = document.createElement('div');
element.innerText = 'Custom Heading';
ctx.appendChild(element);
}
}
})(block);

The Preferences slot allows you to add custom marketing preference fields within the login form. This slot enables merchants to add their own consent options (such as newsletter subscriptions, SMS updates, or promotional offers) based on their specific business needs and compliance requirements.

The slot receives a context with the following properties:

  • email - The current email address entered by the user
  • isEmailValid - A boolean indicating whether the email address is valid
  • isAuthenticated - A boolean indicating whether the user is authenticated
import { render as provider } from '@dropins/storefront-checkout/render.js';
import { LoginForm } from '@dropins/storefront-checkout/containers/LoginForm.js';
await provider.render(LoginForm, {
slots: {
Preferences: (ctx) => {
if (!ctx.isEmailValid || ctx.isAuthenticated) return;
const element = document.createElement('div');
element.innerHTML = `
<label>
<input type="checkbox" name="newsletter" />
Subscribe to our newsletter
</label>
`;
ctx.appendChild(element);
}
}
})(block);

The Title slot allows you to replace the default section heading rendered by the LoginForm container.

import { render as provider } from '@dropins/storefront-checkout/render.js';
import { LoginForm } from '@dropins/storefront-checkout/containers/LoginForm.js';
await provider.render(LoginForm, {
slots: {
Title: (ctx) => {
const heading = document.createElement('h2');
heading.textContent = 'Sign in to continue';
ctx.replaceWith(heading);
}
}
})(block);

The slots for the PaymentMethods container allow you to customize its appearance and behavior.

interface PaymentMethodsProps {
slots?: {
Methods?: PaymentMethodHandlers;
Title?: SlotProps<Record<string, never>>;
};
}

The Methods slot allows you to register custom payment method handlers, replacing or augmenting the built-in payment method UI. Pass an object whose keys are payment method codes and values are handler functions.

The Title slot allows you to replace the default section heading rendered by the PaymentMethods container.

import { render as provider } from '@dropins/storefront-checkout/render.js';
import { PaymentMethods } from '@dropins/storefront-checkout/containers/PaymentMethods.js';
await provider.render(PaymentMethods, {
slots: {
Title: (ctx) => {
const heading = document.createElement('h2');
heading.textContent = 'How would you like to pay?';
ctx.replaceWith(heading);
}
}
})(block);

The slots for the PlaceOrder container allow you to customize its appearance and behavior.

interface PlaceOrderProps {
slots?: {
Content?: SlotProps<ContentSlotContext>;
};
}

The Content slot allows you to customize the content section of the PlaceOrder container.

import { render as provider } from '@dropins/storefront-checkout/render.js';
import { PlaceOrder } from '@dropins/storefront-checkout/containers/PlaceOrder.js';
await provider.render(PlaceOrder, {
slots: {
Content: (ctx) => {
// Your custom implementation
const element = document.createElement('div');
element.innerText = 'Custom Content';
ctx.appendChild(element);
}
}
})(block);

The slots for the ShippingMethods container allow you to fully replace the default shipping method UI with a custom implementation.

interface ShippingMethodsProps {
slots?: {
ShippingMethodItem?: SlotProps<{
method: ShippingMethod;
isSelected: boolean;
onSelect: () => void;
}>;
Title?: SlotProps<Record<string, never>>;
};
}

The ShippingMethodItem slot allows you to replace the default RadioButton or ToggleButton UI for each shipping method with a completely custom element. Use ctx.replaceWith() to provide your own UI and ctx.onRender() to update it when the context changes.

The slot receives a ShippingMethodItemContext with the following properties:

  • method - The shipping method data (ShippingMethod model with carrier, amount, title, and so on.)
  • isSelected - Whether this method is currently selected
  • onSelect - Callback that selects this shipping method and triggers the API call to set it on the cart

The internal presentation component that renders the list also accepts a busy flag (see the checkout drop-in ShippingMethods UI props) when the flow is waiting on pending checkout updates or a shipping estimate. That state is not part of ShippingMethodItemContext.

import { render as provider } from '@dropins/storefront-checkout/render.js';
import ShippingMethods from '@dropins/storefront-checkout/containers/ShippingMethods.js';
function buildShippingMethodCard(ctx) {
const { method, isSelected } = ctx;
const price = method.amount.value === 0
? 'FREE'
: `$${method.amount.value.toFixed(2)}`;
const card = document.createElement('label');
card.className = `custom-shipping-card ${isSelected ? 'custom-shipping-card--selected' : ''}`;
card.innerHTML = `
<input type="radio" name="shipping-method" value="${method.value}"
${isSelected ? 'checked' : ''} style="display:none" />
<div>
<strong>${method.carrier.title}</strong>
<span>${method.title}</span>
<span>${price}</span>
</div>
`;
card.querySelector('input').addEventListener('change', () => {
ctx.onSelect();
});
return card;
}
await provider.render(ShippingMethods, {
slots: {
ShippingMethodItem: (ctx) => {
const card = buildShippingMethodCard(ctx);
ctx.replaceWith(card);
ctx.onRender((updatedCtx) => {
card.className = `custom-shipping-card ${updatedCtx.isSelected ? 'custom-shipping-card--selected' : ''}`;
card.querySelector('input').checked = updatedCtx.isSelected;
});
},
},
})(block);

The Title slot allows you to replace the default section heading rendered by the ShippingMethods container.

import { render as provider } from '@dropins/storefront-checkout/render.js';
import ShippingMethods from '@dropins/storefront-checkout/containers/ShippingMethods.js';
await provider.render(ShippingMethods, {
slots: {
Title: (ctx) => {
const heading = document.createElement('h3');
heading.textContent = 'Choose a delivery option';
ctx.replaceWith(heading);
}
}
})(block);

The slots for the TermsAndConditions container allow you to customize its appearance and behavior.

interface TermsAndConditionsProps {
slots?: {
Agreements?: SlotProps<{
appendAgreement: SlotMethod<{
name: string;
mode: AgreementMode;
translationId?: string;
text?: string;
}>;
}>;
};
}

The Agreements slot allows you to customize the agreements section of the TermsAndConditions container.

import { render as provider } from '@dropins/storefront-checkout/render.js';
import { TermsAndConditions } from '@dropins/storefront-checkout/containers/TermsAndConditions.js';
await provider.render(TermsAndConditions, {
slots: {
Agreements: (ctx) => {
// Your custom implementation
const element = document.createElement('div');
element.innerText = 'Custom Agreements';
ctx.appendChild(element);
}
}
})(block);