# ProductHero

> Premium variant-aware PDP media hero with accessible navigation, thumbnails, autoplay, and swipe

Canonical URL: https://fa7e86e3d553:3005/islands/commerce/product-hero

Premium PDP media hero designed for full-height layouts beside a BuyBox. It
uses the shared carousel runtime, supports mixed image/video media, and can
focus variant-specific media without collapsing the complete gallery.

## Preview

**Category**: Commerce

## Props

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| images | array | Yes | - | Media objects with `url`/`src`, optional `id`, `variantId`, `variantIds`, alt text, fit, position, and video fields |
| layout | enum | No | "splitLeft" | Layout mode: "splitLeft", "splitRight", "fullHeight", "stacked" |
| thumbnails | enum | No | "rail" | Thumbnail style: "rail" (images), "dots" (circles), "none" |
| thumbnailPosition | enum | No | "left" | Where thumbnails appear: "bottom", "left", "right" |
| navigation | `"none" \| "arrows" \| "floatingArrows"` | No | "floatingArrows" | Shared gallery navigation contract |
| aspectRatio | string | No | "3:4" | CSS aspect ratio such as `"3:4"` or `"1:1"` |
| maxHeight | string | No | "85vh" | Maximum height of the media pane |
| transition | enum | No | "fade" | `"none"`, `"slide"`, `"fade"`, `"zoom"`, or `"kenBurns"` |
| listenForVariant | boolean | No | false | Listen for scoped `variant:changed` events |
| variantMediaMode | `"focus" \| "filter" \| "replace"` | No | "focus" | Variant-media behavior |
| autoplay | boolean | No | false | Advance while visible and not being interacted with |
| interval | number | No | 4000 | Autoplay interval in milliseconds |
| hoverAdvance | boolean | No | false | Advance media through pointer interaction |
| loop | boolean | No | true | Wrap Previous/Next navigation |
| swipe | boolean | No | true | Enable touch swipe |

`showIndicators` remains a compatibility alias. New source should use
`thumbnails:"dots"`.

## Embed Example

```html
<lx-island name="ProductHero">
  <script type="application/json">
{
  "images": [
    {
      "id": "front",
      "url": "https://cdn.example.com/product-front.jpg",
      "alt": "Product front"
    },
    {
      "id": "blue-detail",
      "url": "https://cdn.example.com/product-blue.jpg",
      "variantIds": ["gid://shopify/ProductVariant/blue"],
      "alt": "Product in blue"
    }
  ],
  "navigation": "floatingArrows",
  "thumbnails": "rail",
  "listenForVariant": true,
  "variantMediaMode": "focus"
}
  </script>
</lx-island>
```

## Usage Patterns

**Split-hero PDP (with BuyBox in adjacent column):**

```html
<lx-island name="ProductHero">
  <script type="application/json">
{
  "images": [
    {
      "url": "example-url"
    }
  ]
}
  </script>
</lx-island>

<lx-island name="BuyBox">
  <script type="application/json">
{
  "product": {
    "title": "example-title",
    "price": "example-price",
    "variants": []
  }
}
  </script>
</lx-island>
```

**Full-height hero (luxury):**

```html
<lx-island name="ProductHero">
  <script type="application/json">
{
  "images": [
    {
      "url": "example-url"
    }
  ]
}
  </script>
</lx-island>
```

## Navigation contract

- `arrows` keeps Previous and Next visible.
- `floatingArrows` keeps both buttons mounted and keyboard-accessible while
  their visual treatment responds to hover and focus.
- `none` removes arrow controls.
- One-item galleries omit redundant arrows, dots, and carousel semantics.
- Autoplay pauses on hover, keyboard focus, document hiding, and viewport
  exit. Reduced motion disables autoplay and animated transitions.

## Variant-media behavior

With `listenForVariant:true`, matching supports:

- Variant image URL
- Gallery media `id` through `mediaId` or `mediaIds`
- Explicit media `variantId`
- Explicit media `variantIds`
- Multiple media items assigned to one variant

`focus` retains the complete gallery and moves to the first match. `filter`
shows all assigned media without mutating the authored array. `replace` uses
replacement images supplied by the event. A missing match leaves the current
gallery unchanged.

## Coordinates with

- **BuyBox** — Place in an adjacent grid column.
- **VariantSwatches** or **VariantSelector** — Emits scoped variant state.
- Use one shared `data-scope` wrapper per product when several products appear
  on the same page.

## Stylable parts

Stable parts include `root`, `media-pane`, `viewport`, `track`, `slide`,
`image`, `video`, `previous`, `next`, `controls`, `dots`, `dot`,
`thumbnail-rail`, and `thumbnail`.

## Differences from ProductGallery

| Feature | ProductGallery | ProductHero |
|---------|---------------|-------------|
| Layout | Standalone, any position | Split-layout, designed for grid beside BuyBox |
| Per-image fit | Global objectFit only | Per-image objectFit + objectPosition |
| Arrows | Shared persistent or floating navigation | Shared persistent or floating navigation |
| Purpose | Generic gallery | PDP hero section |
| Height | Aspect-ratio based | Viewport-height based (85vh default) |
