# StickyBar

> Persistent product or collection CTA with optional variant and quantity controls and two-way BuyBox synchronization.

Canonical URL: https://fa7e86e3d553:3005/islands/commerce/sticky-bar

StickyBar provides a fixed-bottom CTA after the primary purchase section leaves view.
Optional controls let customers choose a variant and quantity without scrolling back.

## Preview

## Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| product | object | - | Product title, price, variantId, optional image, compareAtPrice, and variants |
| product.variants | array | - | Records with id, title, price, available, optional image and compareAtPrice |
| collection | object | - | Alternative CTA with label, url, optional subtitle and image; no purchase controls |
| cta | string | Add to Cart | Button text; collection mode defaults to its label |
| showVariantSelector | boolean | false | Show a dropdown when the catalog contains more than one variant |
| showQuantitySelector | boolean | false | Show a quantity stepper with a minimum of one |
| syncKey | string | - | Match a BuyBox key to share purchase state; omit for independent purchasing |
| showAfter | string or number | First page section | CSS selector or scroll offset in pixels, including numeric strings |
| animate | boolean or motion mode | true | Entrance animation; respects reduced-motion preference |

Supply either a product or collection. Existing single-variant bars need no changes.
Bound `productId` inputs are resolved into a full variant catalog by the renderer.

## Standalone Controls

```html
<lx-island name="StickyBar">
  <script type="application/json">
  {
    "product": {
      "title": "Even Tone Underarm Mist",
      "price": "₹499",
      "variantId": "gid://shopify/ProductVariant/1001",
      "variants": [
        {"id":"gid://shopify/ProductVariant/1001","title":"Fresh / 100 ml","price":"₹499","available":true},
        {"id":"gid://shopify/ProductVariant/1002","title":"Floral / 100 ml","price":"₹599","available":true}
      ]
    },
    "showVariantSelector": true,
    "showQuantitySelector": true,
    "showAfter": 600
  }
  </script>
</lx-island>
```

Replace example variant IDs with actual catalog IDs. Prices are displayed as supplied;
the bar does not calculate discounts or totals by parsing formatted prices.

## Linking to BuyBox

Set `syncKey: "mist-purchase"` on both islands and provide the same complete variant
catalog. The BuyBox initializes the selection; the sticky bar waits for it before
enabling Add to Cart. This also works with a headless BuyBox.

- Variant and quantity changes in either interface update the other.
- The selected variant controls price, optional image, and availability.
- Scoped inventory updates disable sold-out variants and purchasing without
  silently selecting another variant.
- Both buttons submit the same variant, quantity, and selling plan.
- A shared pending lock prevents simultaneous duplicate cart requests.
- Missing BuyBoxes and mismatched catalogs disable linked purchasing.
- Use a different key for each independent purchase group. No key means no synchronization.

For product-bound pages, the same product ID can supply both catalogs:

```html
<section id="buy-box">
  <lx-island name="BuyBox">
    <script type="application/json">
      {"productId":"gid://shopify/Product/100","syncKey":"mist-purchase"}
    </script>
  </lx-island>
</section>
<lx-island name="StickyBar">
  <script type="application/json">
    {"productId":"gid://shopify/Product/100","syncKey":"mist-purchase","showVariantSelector":true,"showQuantitySelector":true,"showAfter":"#buy-box"}
  </script>
</lx-island>
```

## Subscriptions and Quantity Tiers

Enable `listenForEvents: true` on the linked BuyBox. Place external selectors inside
an authored wrapper whose `data-scope` matches `syncKey`, such as
`<div data-scope="mist-purchase">`. Unscoped or differently scoped events do not
change a synchronized purchase group.

The sticky bar mirrors the effective price and selling plan, without adding plan or
tier selectors of its own. For tier-controlled offers, the variant and quantity controls
are read-only. **Change options** returns focus to the primary purchase area, where
customers use the tier selector. Tier selections remain purchasable from either CTA.

With an active subscription, variant controls are also locked to avoid applying an
unverified plan price to another variant. An external variant change requires a new
plan selection before purchasing; ordinary quantity changes preserve the plan.

## Styling and Accessibility

The default layout is horizontal on desktop and wraps on narrow screens.
Hidden bars are inert, unavailable variants are disabled, and cart failures
show an accessible message while preserving selection for retry. Selectors,
quantity controls, and the CTA use touch-friendly targets. Bottom spacing
includes the device safe area.

| Part | Description |
|------|-------------|
| root, bar | Fixed container and inner layout |
| product-image, product-info | Thumbnail and product details |
| product-title, product-price | Product name and current price |
| variant-selector | Native variant dropdown |
| quantity | Stepper wrapper |
| quantity-decrement, quantity-input, quantity-increment | Quantity controls |
| change-options | Return to the main purchase controls |
| cta, error | Purchase button and failure message |

```css
[data-section-id='sticky-purchase'] [data-part='variant-selector'] {
  border-radius: 12px;
}
```

Pair with [BuyBox](/islands/commerce/buy-box) and an effective
[Cart V2 profile](/guides/cart-v2) for the primary purchase interface and cart
feedback.
