Skip to main content

Product Specifications from Variant Options and Metafields

A Product Information block that shows a specifications table on the product page - the selected variant's options (e.g. size and color) followed by material and care details stored in product metafields - plus a collapsible "Shipping & returns" section.

Example​

import React, { useState } from 'react';
import { Actionable, Box, Flexbox, Icon, Text } from '@evlop/native-components';
import { CustomBlock, loadProductsManager } from '@evlop/shopify';
import Collapsible from 'react-native-collapsible';

loadProductsManager.addMetafieldIdentifiers([
{ namespace: 'custom', key: 'material' },
{ namespace: 'custom', key: 'care_instructions' },
]);

const SHIPPING_AND_RETURNS = 'Free shipping on orders over $50. Unused items can be returned within 30 days.';

const SpecRow = ({ label, value }: { label: string; value?: string }) => {
if (!value) return null;
return (
<Flexbox flexDirection="row" gap={12} py={8} borderBottomWidth={1} borderColor="gray-100">
<Text width="35%" color="gray-500">{label}</Text>
<Text style={{ flex: 1 }}>{value}</Text>
</Flexbox>
);
};

const ProductSpecifications: CustomBlock.ProductInformation = ({ product, variant }) => {
const [isShippingOpen, setShippingOpen] = useState(false);
const selectedOptions = variant?.selectedOptions ?? [];
const metafields = product?.metafields?.custom;

return (
<Box p="md">
<Text fontSize="lg" fontWeight="Bold" mb={8}>Specifications</Text>

{selectedOptions.map((option) => (
<SpecRow key={option.name} label={option.name} value={option.value} />
))}
<SpecRow label="Material" value={metafields?.material} />
<SpecRow label="Care" value={metafields?.care_instructions} />

<Actionable action={() => setShippingOpen(!isShippingOpen)}>
<Flexbox flexDirection="row" alignItems="center" justifyContent="space-between" py={12}>
<Text fontWeight="Semibold">Shipping & returns</Text>
<Icon
icon={isShippingOpen ? 'material-community-icons:minus' : 'material-community-icons:plus'}
size={20}
color="gray-500"
/>
</Flexbox>
</Actionable>
<Collapsible collapsed={!isShippingOpen}>
<Text color="gray-700">{SHIPPING_AND_RETURNS}</Text>
</Collapsible>
</Box>
);
};

export default ProductSpecifications;

How it works​

  • product and variant are top-level props for this block type - not data.product - as explained on the Product Information page.
  • Variant options update with the selection. variant.selectedOptions is a list of { name, value } pairs for the currently selected variant, so the table changes as the shopper picks a different size or color.
  • Metafields are registered once, at module scope. loadProductsManager.addMetafieldIdentifiers(...) sits next to the imports, and each value is read from product.metafields.custom.<key> - see Showing Metafields on a Product Display Card for more on this pattern.
  • Empty rows are skipped. SpecRow returns null when there's no value, so products without a material or care metafield don't show empty rows.
  • Collapsible (from react-native-collapsible) hides the shipping and returns text until the shopper taps its heading. The text is a constant here; move it to a metafield if it differs per product.