Product Discovery Slots
The Product Discovery drop-in exposes 12 slots in 2 containers 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: 2.1.0
| Container | Slots |
|---|---|
Facets | Facet, SelectedFacets, Facets, FacetBucket, FacetBucketLabel |
SearchResults | ProductActions, ProductPrice, ProductName, ProductImage, NoResults, Header, Footer |
Facets slots
interface FacetsProps
slots?: { Facet?: SlotProps<{ data: SearchFacet }>; SelectedFacets?: SlotProps<{ data: SearchFacet[] }>; Facets?: SlotProps<{ data: SearchFacet[] }>; FacetBucket?: SlotProps<{ data: FacetBucket }>; FacetBucketLabel?: SlotProps<{ data: FacetBucket }>;};SearchResults slots
interface SearchResultsProps
slots?: { ProductActions?: SlotProps<SlotDefaultContext>; ProductPrice?: SlotProps<SlotDefaultContext>; ProductName?: SlotProps<SlotDefaultContext>; ProductImage?: SlotProps<SlotDefaultContext & { defaultImageProps: ImageProps }>; NoResults?: SlotProps<{ error: string | null; variables: SearchVariables | null }>; Header?: SlotProps<{ products: Product[]; variables: SearchVariables | null }>; Footer?: SlotProps<{ products: Product[]; variables: SearchVariables | null }>;};ProductActions example
This example from the Product List Page block shows how to customize the ProductActions slot:
import { render as provider } from '@dropins/storefront-product-discovery/render.js';import SearchResults from '@dropins/storefront-product-discovery/containers/SearchResults.js';import { Button, Icon, provider as UI } from '@dropins/tools/components.js';import { h } from '@dropins/tools/preact.js';import { WishlistToggle } from '@dropins/storefront-wishlist/containers/WishlistToggle.js';import { render as wishlistRender } from '@dropins/storefront-wishlist/render.js';// Note: `getAddToCartButton` should be defined in your block context (helper function to create add to cart button)
provider.render(SearchResults, { slots: { ProductActions: (ctx) => { const actionsWrapper = document.createElement('div'); actionsWrapper.className = 'product-discovery-product-actions'; // Add to Cart Button const addToCartBtn = getAddToCartButton(ctx.product); addToCartBtn.className = 'product-discovery-product-actions__add-to-cart'; // Wishlist Button const $wishlistToggle = document.createElement('div'); $wishlistToggle.classList.add('product-discovery-product-actions__wishlist-toggle'); wishlistRender.render(WishlistToggle, { product: ctx.product, variant: 'tertiary', })($wishlistToggle); actionsWrapper.appendChild(addToCartBtn); actionsWrapper.appendChild($wishlistToggle); ctx.replaceWith(actionsWrapper); } }})(document.querySelector('.search-results'));ProductImage example
This example from the Product List Page block shows how to customize the ProductImage slot:
import { render as provider } from '@dropins/storefront-product-discovery/render.js';import SearchResults from '@dropins/storefront-product-discovery/containers/SearchResults.js';import { tryRenderAemAssetsImage } from '@dropins/tools/lib/aem/assets.js';import { getProductLink } from '../../scripts/commerce.js';
provider.render(SearchResults, { slots: { ProductImage: (ctx) => { const { product, defaultImageProps } = ctx; const anchorWrapper = document.createElement('a'); anchorWrapper.href = getProductLink(product.urlKey, product.sku); tryRenderAemAssetsImage(ctx, { alias: product.sku, imageProps: defaultImageProps, wrapper: anchorWrapper, params: { width: defaultImageProps.width, height: defaultImageProps.height, }, }); } }})(document.querySelector('.search-results'));Footer example
This example from the Header block shows how to customize the Footer slot:
import { render as provider } from '@dropins/storefront-product-discovery/render.js';import SearchResults from '@dropins/storefront-product-discovery/containers/SearchResults.js';import { rootLink } from '../../scripts/commerce.js';// Note: `labels` and `recommendationsData` should be defined in your block context
provider.render(SearchResults, { slots: { Footer: async (ctx) => { // View all results button const viewAllResultsWrapper = document.createElement('div'); const viewAllResultsButton = await UI.render(Button, { children: labels.Global?.SearchViewAll, variant: 'secondary', href: rootLink('/search'), })(viewAllResultsWrapper); ctx.appendChild(viewAllResultsWrapper); ctx.onChange((next) => { viewAllResultsButton?.setProps((prev) => ({ ...prev, href: `${rootLink('/search')}?q=${encodeURIComponent(next.variables?.phrase || '')}`, })); }); } }})(document.querySelector('.search-results'));