ProductListAddToCart
Description
The action under a product card. For a simple product it is the Add to Cart button. For a product with variants (colour, size...) it is a Select options link to the product page, because the customer has to choose and a card cannot ask. Adding the card's own variant to the cart would put something in it the customer never picked.
Role in Theming
Core's ProductListItemRender uses it, and a theme's own copy of that card should too. The rule "which action does this product get" then lives in one place, and your card only decides how the action looks.
ProductList still decides whether the action is offered at all (see ProductList). This component decides which action.
Import
import { ProductListAddToCart, hasVariants } from '@components/frontStore/catalog/ProductListAddToCart';
Usage
<ProductListAddToCart product={product} variant="outline" className="w-full" />
Props
| Prop | Type | Required | Description |
|---|---|---|---|
| product | ProductData | Yes | The product the card shows. It needs sku, inventory.isInStock, url and variantGroupId. |
| variant | Button variant | No | The look of the button or link, one of the shared Button's variants. Both actions take the same look. |
| size | Button size | No | One of the shared Button's sizes. |
| className | string | No | Extra classes, merged with the button classes (for example w-full). |
Which action a product gets
| Product | Renders |
|---|---|
| Has no variant group | A Button, "Add to Cart" (and "Adding..." while it works). Errors show as a toast. |
| Has no variant group and is out of stock | A disabled Button that says "Sold out", the word the product page's own button uses. |
Belongs to a variant group (variantGroupId is set) | An <a href={product.url} data-slot="button"> that says "Select options", even when the card's own variant is sold out: another variant may be in stock, and the card cannot tell. It is a link because it navigates, and data-slot="button" keeps it styled by everything that styles buttons. |
Belongs to a variant group and has no url | Nothing. There is nowhere to send the customer, and adding the variant is the one thing not to do. |
hasVariants(product) is the rule on its own: it returns true when variantGroupId is set. It is the same rule core's product resolver and its "configurable" product filter use.
Translations
It uses four strings, all translated in every shipped locale: Add to Cart, Adding..., Sold out and Select options. A theme's own copy of the card that reuses them needs no new translation rows.
Feeding it from your own list
The card learns that a product has variants from variantGroupId, a plain column of the product (unlike variantGroup, which runs queries per product). Select it in the Product fragment of any list or widget you write, or its cards will offer Add to Cart for products that need a choice:
export const fragments = `
fragment Product on Product {
productId
name
sku
variantGroupId
price { regular { value text } special { value text } }
inventory { isInStock }
image { alt url }
url
}
`;
Related Components
- ProductList - Decides whether the action is offered
- AddToCart - The headless add-to-cart logic behind the button
- ProductContext - Product data interface
- VariantSelector - Where the customer chooses on the product page