Storefront widgets

Gift chooser JavaScript API

On this page

window.AndOrQuickview.open(options) opens the gift chooser dialog and returns its <andor-quickview> element. The cart gift slot is the only caller in AndOr today. You can call it from your own code to reuse the same two-step product and variant picker.

Caution The script loads only when needed. The gift slot loads it the first time it needs the chooser, so window.AndOrQuickview may not exist yet. Check for it before you call it.

open(options)

const dialog = window.AndOrQuickview.open(options);
JavaScript

The dialog is a native <dialog> opened with showModal(). It draws in the browser’s top layer, above the page and the theme’s cart drawer. It traps focus, makes the page behind it inert and returns focus to the button that opened it.

Options

Option Type What it does
into element where the dialog is appended. Keep it inside the cart drawer when you open it from the drawer
title string the dialog’s heading
slots number how many picks. Default 1
products array the products to offer (shape below)
price(product, variant) function returns [was, now] text, or null
strings object the dialog’s words (keys below)
onSubmit(picks) function gets the picks. Resolve to close, reject to show the error
onClose() function runs after the dialog closes, added or not
buttonClass string extra classes for the Add button

products

Each product is { id, title, image, options, variants, swatches }:

  • options is [{ name, values }].
  • Each variant is { id, title, price, available, options, image }.
  • A variant that is not available may add reason. The chooser says the reason instead of “Sold out”.
  • swatches is optional. It maps an option’s position (1 based, as a string) to a list of [name, swatch] pairs. A swatch is a CSS color or an image URL. Example: { "1": [["Red", "#c0392b"], ["Blue", "#1f4e9c"]] }. An option is drawn as swatches only when every value has one. Without a listed swatch, an option named like a color tries the value’s name as a CSS color, else it is drawn as pills.

price

price(product, variant) returns two strings, [was, now], for example ["$24.95", "Free"], or null. variant is null on a product card in step 1. Return null when you are not sure of the price or of “Free”: the chooser then shows no price at all.

strings

Keys: close, back, add, addMany, slot, products, optionsTitle, options, chosen, soldOut, clear, error. In addMany, slot, chosen and clear, @ and # are filled in. For example "Add @ gifts" becomes “Add 2 gifts”, and "Gift @ of #" becomes “Gift 1 of 2”.

The chooser has no built-in words. Pass every key you need.

onSubmit

onSubmit(picks) gets [{ product, variant }], one entry per filled slot. Return a promise. Resolve it to close the dialog. Reject it to show the error string and keep the dialog open.

Example

JavaScript · 43 lines
Show the code
function openGiftPicker(button) {
  if (!window.AndOrQuickview) return; // not loaded on this page yet
  window.AndOrQuickview.open({
    into: button.closest("cart-drawer") || document.body,
    title: "Choose your free gift",
    slots: 1,
    products: [
      {
        id: 111,
        title: "Ski wax",
        image: "https://cdn.shopify.com/.../wax.jpg",
        options: [{ name: "Scent", values: ["Pine", "Citrus"] }],
        swatches: {}, // no swatches: Scent is drawn as pills
        variants: [
          { id: 1, title: "Pine", price: 2495, available: true,
            options: ["Pine"], image: null },
          { id: 2, title: "Citrus", price: 2495, available: false,
            options: ["Citrus"], image: null },
        ],
      },
    ],
    price: () => null, // not sure it is free: show no price
    strings: {
      close: "Close", back: "Back", add: "Add gift",
      addMany: "Add @ gifts", slot: "Gift @ of #",
      products: "Choose a product", optionsTitle: "Choose your options",
      options: "Choose options", chosen: "@ of # gifts chosen",
      soldOut: "Sold out", clear: "Remove @",
      error: "We could not add your gift. Please try again.",
    },
    onSubmit: (picks) =>
      fetch("/cart/add.js", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          items: picks.map(({ variant }) => ({ id: variant.id, quantity: 1 })),
        }),
      }).then((response) => {
        if (!response.ok) throw new Error("add failed");
      }),
    onClose: () => button.focus(),
  });
}

Behavior to know

  • Escape closes the chooser and leaves Dawn’s cart drawer open. A cancel event is stopped too.
  • Everything is drawn with textContent. No product data becomes HTML.
  • The Add button also gets the class list of your theme’s checkout button ([name="checkout"]) when the page has one, so it looks like your primary button on Dawn and Horizon.
  • The chooser adds its own stylesheet the first time the script runs. A first open with the stylesheet still loading keeps the dialog invisible until it loads, for 800 ms at most.

Next steps

Last updated

Was this page helpful?

No

Questions? Email andor@backtrackhq.com or use the chat in the app.