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/