Showing a Merchant-Selected Product
A Section that always shows one specific product picked by the merchant - a "Featured Product" spotlight - rather than one row of a product list (that's what Product List Item Display Card is for) or the active product on the PDP (that's Product Information).
Settings panel
Add a product field to configurationSchema.json. This opens Shopify's native product picker in the settings panel:
[
{
"label": "Product",
"name": "product",
"type": "product"
}
]
Once the merchant picks a product, data.product resolves to a full ShopifyProduct - not just the id/handle they picked, but the same shape (title, description, images, variants, actions) documented on Product List Item Display Card.
Example
import React from 'react';
import { Flexbox, Image, Text, Button } from '@evlop/native-components';
import { Money, CustomBlock } from '@evlop/shopify';
const FeaturedProduct: CustomBlock.Section = ({ data }) => {
if (data?.product?.loading) return <Text p="md">Loading product...</Text>;
if (!data?.product) return <Text p="md">No product selected.</Text>;
const { product } = data;
return (
<Flexbox flexDirection="column" alignItems="center" gap={10} p="md">
<Image src={product.images[0].src} aspectRatio={1} width="100%" borderRadius={8} />
<Text fontSize="xl" fontWeight="Bold" textAlign="center">{product.title}</Text>
<Text textAlign="center" numberOfLines={2}>{product.description}</Text>
<Money price={product.variants[0].price} fontWeight="Bold" />
<Button action={product.actions.addToCart}>Add to Cart</Button>
</Flexbox>
);
};
export default FeaturedProduct;
How it works
- Guard both states before rendering.
data.product?.loadingwhile the picked product is still resolving, then!data.productfor when no product has been picked yet (the field is optional/unset) - two different empty states, both worth their own message rather than letting the rest of the component crash on a missingproduct. This{ loading: true }placeholder is specific to aproductconfigurationSchema field resolving - it's a different shape from the{ isLoading: true }placeholder documented on Product List Item Display Card, which is a separate, per-list-item data path. - Everything else is the same styled-system component pattern used throughout these docs -
Flexbox/Image/Text/Buttonwith plain props, no extra styling library needed.
price, not moneyMoney from @evlop/shopify takes a price prop (a { amount, currencyCode } object) or, alternatively, separate amount/currencyCode string props - never a money prop. That name belongs to a different Money component, the one built into plain EDL markup. Mixing the two up (<Money money={...} /> with the @evlop/shopify import) silently renders nothing, since none of price/amount/currencyCode end up set.
Need more than one product? See Showing Several Merchant-Selected Products.