# OptionResolver

> Invisible island that resolves multi-axis option selections into a single variant. Use when product has 2+ option axes.

Canonical URL: https://fa7e86e3d553:3005/islands/commerce/option-resolver

> Invisible island that resolves multi-axis option selections into a single variant. Use when product has 2+ option axes (e.g. Sugar × Size). Listens for option:changed from VariantSwatches in axis mode, resolves matching variant, emits variant:changed downstream to BuyBox/ProductGallery. Renders nothing visible.

## Preview

**Category**: Commerce

## Props

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| variants | array | Yes | - | Array of variant objects with id, selectedOptions (array of name/value pairs), price, compareAtPrice (optional), available, image (optional), images (optional) |
| options | array | Yes | - | Array of option objects with name, position |
| defaultSelections | object | No | - | Default selections as key-value pairs (e.g., `{"Color": "Red", "Size": "M"}`) |

## Embed Example

```html
<lx-island name="OptionResolver">
  <script type="application/json">
{
  "variants": [
    {
      "id": "example-id",
      "selectedOptions": "example-selectedOptions",
      "price": "example-price",
      "available": true
    }
  ],
  "options": [
    {
      "name": "example-name",
      "position": 0
    }
  ]
}
  </script>
</lx-island>
```

## Usage Patterns

**Standard multi-axis setup (Color × Size):**

```html
<lx-island name="VariantSwatches">
  <script type="application/json">
{}
  </script>
</lx-island>

<lx-island name="OptionResolver">
  <script type="application/json">
{
  "variants": [
    {
      "id": "example-id",
      "selectedOptions": "example-selectedOptions",
      "price": "example-price",
      "available": true
    }
  ],
  "options": [
    {
      "name": "example-name",
      "position": 0
    }
  ]
}
  </script>
</lx-island>

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

**With runtime resolution (productId prop):**

```html
<lx-island name="OptionResolver">
  <script type="application/json">
{
  "variants": [
    {
      "id": "example-id",
      "selectedOptions": "example-selectedOptions",
      "price": "example-price",
      "available": true
    }
  ],
  "options": [
    {
      "name": "example-name",
      "position": 0
    }
  ]
}
  </script>
</lx-island>
```

**With explicit variant data (no fetch):**

```html
<lx-island name="OptionResolver">
  <script type="application/json">
{
  "variants": [
    {
      "id": "example-id",
      "selectedOptions": "example-selectedOptions",
      "price": "example-price",
      "available": true
    }
  ],
  "options": [
    {
      "name": "example-name",
      "position": 0
    }
  ]
}
  </script>
</lx-island>
```

## Events

| Event | Direction | Payload |
|-------|-----------|---------|
| option:changed | Listens | `{axis: string, value: string}` from VariantSwatches in axis mode |
| variant:changed | Emits | `{variantId: string, price: string, compareAtPrice?: string, available: boolean, image?: string, images?: array}` when full selection resolved |
| variant:unavailable | Emits | `{selectedOptions: object}` when selected combination doesn't exist |

## Tips

- **INVISIBLE** — renders no UI, only logic
- Required for products with 2+ option axes (e.g., Color × Size, Flavor × Quantity, Material × Finish)
- Listens to `option:changed` events from multiple [VariantSwatches](/islands/commerce/variant-swatches) islands in axis mode
- Resolves the matching variant from the full variant matrix (e.g., "Red" + "M" → "gid://shopify/ProductVariant/42")
- Emits `variant:changed` downstream to [BuyBox](/islands/commerce/buy-box), [ProductGallery](/islands/commerce/product-gallery), [InventoryIndicator](/islands/commerce/inventory-indicator), [PaymentOptions](/islands/commerce/payment-options)
- When using OptionResolver, set [BuyBox](/islands/commerce/buy-box) `showVariantSelector:false` (VariantSwatches handles selection UI)
- Always set [BuyBox](/islands/commerce/buy-box) `listenForEvents:true` to receive `variant:changed`
- If a selection is invalid (e.g., "Red" + "XL" doesn't exist), emits `variant:unavailable` → VariantSwatches can show "Out of Stock" UI
- Use `defaultSelections` to pre-select options (e.g., default to first available variant)
- For single-option products, use [VariantSwatches](/islands/commerce/variant-swatches) in flat mode (no OptionResolver needed)

## Related Islands

- [VariantSwatches](/islands/commerce/variant-swatches) — Emits `option:changed` in axis mode → OptionResolver listens
- [BuyBox](/islands/commerce/buy-box) — Listens to `variant:changed` from OptionResolver; set `showVariantSelector:false` + `listenForEvents:true`
- [ProductGallery](/islands/commerce/product-gallery) — Listens to `variant:changed` to swap images
- [InventoryIndicator](/islands/commerce/inventory-indicator) — Listens to `variant:changed` to show per-variant stock
- [PaymentOptions](/islands/commerce/payment-options) — Listens to `variant:changed` to update BNPL price
