Skip to content

Product Display Components ​

Components for the product detail page - gallery, cards, tabs, variant pickers, and layout.

Product page - gallery, variant swatches, quantity stepper, add to cart

Component Slots ​

SlotVariantsDefaultDescription
cardStandard, Minimal, Horizontal, FeaturedstandardProduct card in grids
galleryCarousel, Grid, SinglecarouselProduct image gallery
layoutMasonrymasonryProduct page layout
variant-pickerSwatch, Dropdown, ButtonswatchConfigurable option selector
tabsAccordion, TabbedtabbedProduct info tabs (description, specs, reviews)
price--Price display with sale/tier pricing
badge--Sale, new, out-of-stock badges
quantity-stepper--+/- quantity selector
sticky-atc--Sticky add-to-cart bar on scroll
stock-indicator--In stock / low stock / out of stock
info-panel--Shipping, returns, warranty info
breadcrumb--Category breadcrumb trail
recently-viewed--Recently viewed products carousel

Card Variants ​

CardStandard ​

Full-featured card with image, price, ratings, quick-add button, and color swatches.

┌──────────────────┐
│                  │
│     [Image]      │
│                  │
├──────────────────┤
│ Product Name     │
│ ★★★★☆ (12)      │
│ $49.95  $39.95   │
│ [● ● ● ●]       │
│ [Add to Cart]    │
└──────────────────┘

CardMinimal ​

Borderless, image-focused card. Image zooms on hover. No quick-add button - click navigates to product page.

┌──────────────────┐
│                  │
│   [Image zoom]   │
│                  │
│ Product Name     │
│ $49.95           │
└──────────────────┘

CardHorizontal ​

Landscape card for list-view layouts. Image on left, details on right.

CardFeatured ​

Oversized card for hero product placement. Larger image, prominent pricing.

GalleryCarousel ​

Horizontal thumbnail strip below main image. Click thumbnails to switch. Supports keyboard arrow navigation and mobile swipe gestures.

GalleryGrid ​

All images displayed in a grid layout. No carousel - all images visible at once. Ideal for products with few images.

GallerySingle ​

Single large image only. Minimal layout for simple products.

Variant Picker ​

VariantSwatch ​

Color/size options as clickable swatches. Colors show actual color circles. Sizes show text labels. Unavailable combinations are crossed out.

VariantDropdown ​

Traditional dropdown selects for each configurable attribute. Shows available stock for each option.

VariantButton ​

Button-style option selection. Each option is a toggleable button in a row.

Tabs Variants ​

TabsAccordion ​

Collapsible sections for description, specifications, reviews, related, and upsell products. Description open by default. Best suited for sidebar layouts.

TabsTabbed ​

Full-width sections below the fold. Each section (description, specifications, reviews, related, upsell) gets its own block. Best for standard 2-column layouts.

Specifications Tab ​

Both tab variants include a specifications section that displays additional product attributes marked as "Visible on Product View Page" in the Maho admin. Controlled via showSpecifications in page.json sections.

Attributes rendered as a table with label/value pairs. Core attributes (name, SKU, price, etc.) are excluded - only custom product attributes appear.

Product Options ​

The per-product-type option UI (configurable swatches, bundle selections, downloadable link checkboxes, giftcard amount + recipient fields, custom options, etc.) is centralised in src/templates/components/product-options/. Layouts render a single <ProductOptions> dispatcher instead of duplicating the type-branching inline.

Files ​

FileRenders when
ConfigurableOptions.tsxproduct.type === 'configurable' — swatch/attribute buttons; accepts a swatchMap for color-image thumbnails
GroupedOptions.tsxproduct.type === 'grouped' — qty steppers per child; variant='compact' = flex row, variant='standard' = full table with thumbnails
BundleOptions.tsxproduct.type === 'bundle' — <select>/radio/checkbox per option plus a qty stepper for options with canChangeQty
DownloadableOptions.tsxproduct.type === 'downloadable' — link list with sample-file links
GiftcardOptions.tsxproduct.type === 'giftcard' — amount (fixed dropdown / range input / combined), sender + recipient + message + delivery-date
CustomOptions.tsxAny product with product.customOptions — drop-down/checkbox/radio/file/textarea/date/text
index.tsxProductOptions dispatcher — the entry point layouts use

Dispatcher props ​

tsx
<ProductOptions
  product={product}
  currency={currency}
  formatPrice={formatPrice}
  swatchMap={swatchMap}          // color-swatch image URLs (configurable only)
  variant="compact"              // 'compact' (default) or 'standard'
  excludeConfigurable={false}    // skip configurable when the layout renders it elsewhere
/>
  • variant — 'compact' (default) uses narrow-column DaisyUI styling. 'standard' swaps GroupedOptions for a wider table with thumbnails and full qty steppers. All other option components use the same DaisyUI classes regardless of variant.
  • excludeConfigurable — used by Product.tsx (the standard layout) because it renders <ConfigurableOptions> inside its sticky add-to-cart bar rather than inline with the other option blocks.

Data attributes (JS contract) ​

The JS controller reads inputs from the DOM via data-* attributes wired by these components. Keep them stable when adding new markup:

AttributeSource componentRead by
data-attribute-code, data-valueConfigurableOptionsproduct#selectOption (variant resolution)
data-grouped-idGroupedOptions_buildGroupedBody
data-bundle-option-id, data-bundle-qty-optionBundleOptions_buildBundleBody, product#updateBundlePrice
data-download-link-idDownloadableOptions_buildDownloadableBody
data-giftcard-fieldGiftcardOptions_buildGiftcardBody
data-custom-option-id, data-custom-option-file-idCustomOptions_appendCustomOptions, _appendOptionFiles

See product controller for how each attribute maps to the outgoing API payload.

Configuration ​

json
{
  "pages": {
    "product": {
      "components": {
        "gallery": "carousel",
        "card": "minimal",
        "variant-picker": "swatch",
        "tabs": "accordion",
        "layout": "masonry"
      },
      "sections": {
        "showSpecifications": true,
        "showReviews": true,
        "reviewsPosition": "tabbed",
        "showRelated": true,
        "showRecentlyViewed": true
      }
    }
  }
}

Source: src/templates/components/product-display/