Generated from the typings of
@quickbutik/kit@1.8.0 as published on npm. Do not edit this page by hand: run npm run generate in tools/kit-api-reference. For guided, example-led documentation see the API reference.Classes
ContextRequestEvent
The event itself. A class rather than aCustomEvent with a detail, because
that is what the protocol specifies and what other libraries (Lit’s
@lit/context, notably) listen for — an app already using Lit contexts can
provide to, or consume from, these elements without an adapter.
Extends
Event
Type Parameters
Constructors
Constructor
Parameters
Returns
ContextRequestEvent<T>
Overrides
Properties
callback
context
subscribe
QbAddToCartElement
<qb-add-to-cart> — wraps the author’s own button and makes it work.
<button> is the page’s, with its own classes and its own
label. What this contributes is the part every storefront otherwise rewrites
— a product with options must not be addable until exactly one variant is
pinned, and the cart needs the variant id rather than the product id.
Any click inside it adds, so a whole card can be the target. It keeps the
inner controls’ disabled in step with whether adding is possible right now,
and reflects disabled / pending on itself for styling. Quantity comes from
quantity="2", data-qb-quantity on the clicked element, or a nearby
input[data-qb-quantity-input].
data-qb-action="add-to-cart" on a plain button inside <qb-product> does
the same thing without the disabled-state management — use that when the
button lives somewhere this element cannot wrap.
Extends
Constructors
Constructor
Returns
QbAddToCartElement
Inherited from
QbElement.constructor
Properties
observedAttributes
Methods
add()
disabled — the same guard the inner button’s
disabled reflects, so a programmatic call cannot get past it either.
Parameters
Returns
Promise<void>
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbElement.attributeChangedCallback
connectedCallback()
Returns
void
Inherited from
QbElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbElement.disconnectedCallback
QbBuyNowElement
<qb-buy-now> — “Köp nu”: add the selected variant and go straight to the
hosted checkout.
<qb-add-to-cart>: it must sit inside a <qb-product>, it is blocked until
exactly one variant is pinned, quantity comes from quantity="2",
data-qb-quantity on the clicked element or a nearby
input[data-qb-quantity-input], and the inner controls’ disabled is kept
in step. From <qb-checkout-button>: success-url, back-url and theme
mean the same thing and are resolved by the same code, no-redirect stops
short of navigating, and qb:checkout-started carries the handoff.
The item goes into the REMEMBERED cart, so a basket the shopper already
filled is checked out with it rather than replaced — “buy this too, now”,
which is what the button means on every storefront that has one. The shared
cart store sees the add, so a <qb-cart-count> on a page the shopper comes
back to (the back button, no-redirect) is not one item short.
Adds no markup. data-qb-action="buy-now" on a plain button inside
<qb-product> does the same thing without the disabled-state management.
Extends
Constructors
Constructor
Returns
QbBuyNowElement
Inherited from
QbElement.constructor
Properties
observedAttributes
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbElement.attributeChangedCallback
buy()
<qb-product> emits
qb:add-to-cart-blocked with the groups still missing a choice), while
one is already in flight, or while the element carries disabled. After
it navigates it stays busy until the page is restored from the
back/forward cache, so a click while the checkout loads buys nothing.
no-redirect emits qb:checkout-started and stays put — for a page that
opens the checkout in a new tab, or runs its own analytics first.
Parameters
Returns
Promise<void>
connectedCallback()
Returns
void
Inherited from
QbElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbElement.disconnectedCallback
QbCartCountElement
<qb-cart-count> — the badge. Sets its own text to the number of items.
The one element here that writes its own content, because there is nothing
else it could be: a badge IS its number. zero is reflected as an attribute
so an empty badge can be hidden in CSS.
Extends
Constructors
Constructor
Returns
QbCartCountElement
Inherited from
QbElement.constructor
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbElement.attributeChangedCallback
connectedCallback()
Returns
void
Inherited from
QbElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbElement.disconnectedCallback
QbCartElement
<qb-cart> — the shopper’s basket as a scope for the markup inside it.
state, empty and pending as attributes. Handles the clear
(alias clear-cart) and refresh actions. clear empties the basket —
deletes the remembered cart and forgets it — and does nothing when there is
no cart; a cart the server already dropped still ends up cleared.
Extends
CartAwareElement
Constructors
Constructor
Returns
QbCartElement
Inherited from
Properties
observedAttributes
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
connectedCallback()
Returns
void
Inherited from
disconnectedCallback()
Returns
void
Inherited from
QbCartItemsElement
<qb-cart-items> — one <template> clone per cart line.
Scope inside a row: everything on the API’s CartItem, plus the formatted
money fields (item.lineTotalFormatted, item.unitPriceFormatted, …) and
item.onSale.
Handles remove, increment and decrement, and binds any
input[data-qb-quantity] in the row to that line’s quantity — with the
change committed on change rather than on every keystroke, so typing 12
does not first send a quantity of 1.
Rows are keyed by cart line id and reused across updates. Without that the
quantity input the shopper is typing in is replaced mid-keystroke and loses
both its value and the caret.
Extends
CartAwareElement
Constructors
Constructor
Returns
QbCartItemsElement
Inherited from
Properties
observedAttributes
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
connectedCallback()
Returns
void
Inherited from
disconnectedCallback()
Returns
void
Inherited from
QbCheckoutButtonElement
<qb-checkout-button> — hands the shopper to the hosted Quickbutik checkout.
theme="dark" paints the hosted checkout dark for this shopper. Omit it and
the merchant’s own choice applies — see checkoutTheme.
Payment is deliberately not part of this: the hosted checkout owns the PSP
integration, PCI scope, 3-D Secure and wallets. This creates the session,
builds the handoff URL and sends the shopper there.
Extends
Constructors
Constructor
Returns
QbCheckoutButtonElement
Inherited from
QbElement.constructor
Properties
observedAttributes
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbElement.attributeChangedCallback
checkout()
no-redirect stops it short of navigating and emits qb:checkout-started
with the URL instead — for a page that wants to open the checkout in a new
tab, or to run its own analytics first.
Returns
Promise<void>
connectedCallback()
Returns
void
Inherited from
QbElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbElement.disconnectedCallback
QbCheckoutElement
<qb-checkout> — the Quickbutik checkout, inside your own page.
<iframe> and nothing else. The document inside is served from the
checkout’s own origin, so the payment integration, 3-D Secure and the wallet
domain registrations all work exactly as they do when the shopper is
redirected — what changes is that they never leave your page.
Not a replacement for <qb-checkout-button>: the button is still the right
element for a cart page that hands the shopper off, and it is what this
element degrades to when embedding is not possible (see below). Both create
the session the same way, from the same attributes.
theme="light" or theme="dark" paints the frame to match your own pages
rather than following the theme the merchant chose for their shop. Read once
with everything else, when the session is created — a page that toggles its
own dark mode under a live checkout does not repaint it. See
checkoutTheme.
Four things happen automatically, and each is a thing a hand-rolled iframe
would get wrong:
- The frame’s height follows its content, so there is never a scrollbar
inside a scrollbar.
min-heightis the floor, and the height before the first measurement arrives. - A redirect payment method breaks out to the top window. Klarna, Swish,
Vipps/MobilePay, iDEAL, Trustly and a full-page 3-D Secure all navigate
the whole window to the PSP, come back to the checkout’s own origin, and
bounce to this page with
?qb_checkout_session=…&qb_checkout_shop=…. This element picks both up on load, resumes the same session from the URL alone — the cart, and the store id remembered with it, are normally gone by then, because the order exists — and, once the frame has answered, cleans the parameters out of the address bar so a reload does not try to resume a consumed session. If the resume never gets that far, the parameters stay, so a reload resumes again instead of starting a new checkout. - It degrades rather than strands the shopper. A shop on the legacy
checkout, a platform with no embed URL, or a page that cannot navigate its
own top window all fall back to the redirect checkout and emit
qb:checkout-fallbackbefore any frame exists. A frame that is built but never answers — this page is not the origin the session was created for, most often — is taken down after 15 seconds and falls back the same way, withdetail.reason === "handshake-timeout"; it never ends instate="error". - It follows the cart. Change the cart from the page while the frame is
up —
Quickbutik.cart.add(), a quantity stepper of your own — and the checkout re-reads it and re-prices itself, so it never charges for a cart the shopper has already moved on from. Nothing is mounted while the cart is empty or still loading (qb:checkout-emptysays so, once); the frame goes in when items exist. Empty the cart from the page —Quickbutik.cart.clear(), the last line removed — while a frame is up, and the frame comes down with it, because the session it shows names a cart that no longer exists; the next item added starts a fresh session. A frame that is resuming a return leg, or showing a completed order, is left alone: there the cart is SUPPOSED to be gone.
qb:checkout-ready, qb:checkout-step,
qb:checkout-event (GA4-shaped commerce events for your own dataLayer),
qb:checkout-complete, qb:checkout-error, qb:checkout-fallback, and
qb:checkout-empty when there is nothing in the cart to check out.
Extends
Constructors
Constructor
Returns
QbCheckoutElement
Inherited from
QbElement.constructor
Properties
observedAttributes
Accessors
checkout
Get Signature
Returns
EmbeddedCheckout | null
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbElement.attributeChangedCallback
connectedCallback()
Returns
void
Inherited from
QbElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbElement.disconnectedCallback
QbConsentBannerElement
<qb-consent-banner> — the cookie banner, headless.
qb-consent*
class names (the same ones the React <ConsentBanner> renders) and reads
its copy from the built-in labels for lang, falling back to <html lang>
and then English. It comes styled: one stylesheet in <head>, in
@layer qb-consent so the page’s own rules win, themed through
--qb-consent-* custom properties. unstyled leaves it out.
A page configured through configure(), <qb-shop> or the script tag
gets one of these appended to <body> automatically (consent is on by
default). Placing one yourself replaces that one, so there is never a
second dialog.
Given children, it binds them instead, so a shop with its own voice writes
its own banner:
accept-all, reject-all, save (reads every
input[data-qb-consent] inside the banner), open-settings,
close-settings. Scope: consent.status, consent.undecided,
consent.decided, consent.open, consent.analytics, consent.marketing,
consent.labels.*, consent.privacyPolicyUrl.
Reflected: status="undecided|decided", open while the preferences panel
is shown, and the native hidden attribute once the shopper has decided —
unless show-when-decided is set, or the panel is open again (a
<qb-consent-settings> link in the footer reopens it). The decision itself
lives in the page’s ambient ConsentStore (see configureConsent), which
writes the qb_consent cookie and dispatches qb:consent on document.
Extends
Constructors
Constructor
Returns
QbConsentBannerElement
Inherited from
QbScopeElement.constructor
Properties
observedAttributes
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbScopeElement.attributeChangedCallback
connectedCallback()
Returns
void
Inherited from
QbScopeElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbScopeElement.disconnectedCallback
save()
Returns
void
QbConsentGateElement
<qb-consent-gate> — markup that exists only with consent.
<template> child is the gated content; every other child is
the placeholder. While the category is denied the placeholder shows and the
template’s content is not in the document at all — an <iframe> or a
<script> inside it is never fetched. When the shopper grants it, the
content is cloned in after the placeholder and the placeholder is hidden;
when they withdraw it, the clones are removed again. Reflects
state="granted|denied".
Extends
Constructors
Constructor
Returns
QbConsentGateElement
Inherited from
QbElement.constructor
Properties
observedAttributes
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbElement.attributeChangedCallback
connectedCallback()
Returns
void
Inherited from
QbElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbElement.disconnectedCallback
QbConsentSettingsElement
<qb-consent-settings> — a “Cookie settings” link, anywhere on the page.
open lives in it. Reflects status="undecided|decided" like the banner,
so the link can read “Cookie settings (analytics on)” through CSS or a
binding of the page’s own.
Left empty, it renders a <button type="button"> with the built-in label
for lang (“Cookie settings”, “Cookie-inställningar”, …), the same thing
React’s <ConsentSettingsButton> renders: an empty element would be a
footer link nobody can click. Hidden when the page turned consent off.
Extends
Constructors
Constructor
Returns
QbConsentSettingsElement
Inherited from
QbElement.constructor
Properties
observedAttributes
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbElement.attributeChangedCallback
connectedCallback()
Returns
void
Inherited from
QbElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbElement.disconnectedCallback
QbCurrencySelectElement
<qb-currency-select> — let the shopper pick the currency the shop is
browsed in.
Three ways to write it, from least to most markup:
client.setCurrency(): the choice is remembered, every
<qb-product> and <qb-product-list> refetches its prices in it, and every
cart element re-reads the SAME cart in it. A "display" currency is shown
converted and charged in the shop’s currency at checkout; a "charge"
currency is priced and charged in it.
Scope: currency.code (what prices are shown in), currency.base,
currency.mode (base / display / charge), currency.chargeCurrency,
currency.count; inside a template row, option.code, option.label,
option.name, option.mode, option.rate, option.selected,
option.base. Rows get data-selected and data-currency.
Reflects state, data-currency, data-mode, and empty when the shop
offers nothing but its own currency — qb-currency-select[empty] { display: none } hides a switcher with nothing to switch. Emits
qb:currency-change with { currency } after a choice. label="name" (or
"code-name") labels the options with the currency’s name in locale.
Reads the shop with shop.get(), so the key needs checkout:read — every
standard storefront key has it.
Extends
Constructors
Constructor
Returns
QbCurrencySelectElement
Inherited from
QbScopeElement.constructor
Properties
observedAttributes
Accessors
info
Get Signature
Returns
CurrencyInfo | null
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbScopeElement.attributeChangedCallback
choose()
Parameters
Returns
Promise<void>
connectedCallback()
Returns
void
Inherited from
QbScopeElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbScopeElement.disconnectedCallback
abstract QbElement
Base for every element in this package.
It exists for three things that every one of them needs and that are easy to
get subtly wrong: not reading children before the parser has produced them,
unwinding subscriptions on disconnect, and finding the shop.
No shadow DOM anywhere. These are headless components: the merchant’s own
stylesheet has to reach the markup, and a shadow root is precisely a wall
against that.
Extends
HTMLElement
Extended by
QbAddToCartElementQbBuyNowElementQbCartCountElementQbCheckoutButtonElementQbCheckoutElementQbConsentGateElementQbConsentSettingsElementQbProductImageElementQbScopeElementQbSeoElementQbShopElement
Constructors
Constructor
Returns
QbElement
Inherited from
Methods
attributeChangedCallback()
Parameters
Returns
void
connectedCallback()
Returns
void
disconnectedCallback()
Returns
void
QbOptionsElement
<qb-options> — repeats its <template> once per option group the product
actually has, in the product’s own display order.
Scope inside a row: group.id, group.name, group.position,
group.values, group.selectedValueId, group.chosen.
A product with no options renders nothing and the element is marked empty,
so qb-options[empty] { display: none } hides the surrounding chrome.
Extends
OptionsRepeatElement
Constructors
Constructor
Returns
QbOptionsElement
Inherited from
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
connectedCallback()
Returns
void
Inherited from
disconnectedCallback()
Returns
void
Inherited from
QbOptionValuesElement
<qb-option-values> — repeats its <template> once per value of the group
it sits in.
Nested inside a <qb-options> row it needs no attributes at all: the group
comes from the row’s scope. Scope inside a value row: value.id,
value.name, value.selected, value.available, value.unavailable,
value.variantIds — plus everything the enclosing scopes offered.
Each row’s top-level elements get data-selected and data-available
reflected, aria-pressed set, and — on a <button> or <input> — the
disabled property, so unavailable combinations are a stylesheet’s concern.
option="<id or name>" is an escape hatch for the deliberate case: a layout
that wants swatches for one particular group and a plain row for the rest.
It is never required, and pinning it to a name means the picker stops working
on a product whose merchant named that option something else.
Extends
OptionsRepeatElement
Constructors
Constructor
Returns
QbOptionValuesElement
Inherited from
Properties
observedAttributes
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
connectedCallback()
Returns
void
Inherited from
disconnectedCallback()
Returns
void
Inherited from
QbOrderConfirmationElement
<qb-order-confirmation> — the thank-you page.
completed, failed or timeout, reflecting each as both a scope
flag and a status attribute.
The session id comes from session-id, from a ?session_id= query parameter,
or — with neither — from the session shopkit remembered when the checkout was
created.
With analytics on (configure({ analytics }), <qb-shop analytics>) a
completed order is reported as a purchase event, once per browser, built
from the session’s own lines and total. The hosted checkout never fires it
in redirect mode — this page is the thank-you page, so this is where it
belongs. no-track-purchase turns that off for a page that reports the
order itself; in inline success mode the embedded frame already did.
Extends
Constructors
Constructor
Returns
QbOrderConfirmationElement
Inherited from
QbScopeElement.constructor
Properties
observedAttributes
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbScopeElement.attributeChangedCallback
connectedCallback()
Returns
void
Inherited from
QbScopeElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbScopeElement.disconnectedCallback
QbProductElement
<qb-product> — one product, its variant selection, and everything derived
from the two.
Resolves the product itself, so a page can name it by slug and write no
JavaScript at all:
state="loading|ready|error", plus empty, complete / incomplete — so a
skeleton and a “choose a size first” hint are pure CSS. The product can also
be handed in as a property (el.product = product) when the page fetched it
already.
A slug lookup costs a catalog walk, because the storefront API has no slug
filter. On a large catalog prefer resolving the product server-side and
assigning the property.
Extends
Constructors
Constructor
Returns
QbProductElement
Inherited from
QbScopeElement.constructor
Properties
observedAttributes
Accessors
product
Get Signature
slug / product-id.
Returns
Product | null
Set Signature
Parameters
Returns
void
selection
Get Signature
Returns
ProductController | null
Methods
addToCart()
qb:add-to-cart-blocked, carrying the groups still missing a choice, so a
page can prompt for them.
Parameters
Returns
Promise<Cart | null>
attributeChangedCallback()
Parameters
Returns
void
Overrides
QbScopeElement.attributeChangedCallback
buyNow()
url and all) and does NOT navigate; the
buy-now verb and <qb-buy-now> do that.
The guard is addToCart’s: while the selection is incomplete it
emits qb:add-to-cart-blocked and resolves to null, because buying is
adding. A second call while one is in flight also resolves to null — two
clicks would otherwise add the item twice before either navigation
lands. A failed handoff THROWS (see CartStore.buyNow); the verb and the
element turn that into a qb:error. input may be a function, called
only once the guard has passed — so a blocked click does not also warn
about a missing success-url.
Parameters
Returns
Promise<BuyNowResult | null>
canAddToCart()
Returns
boolean
connectedCallback()
Returns
void
Inherited from
QbScopeElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbScopeElement.disconnectedCallback
QbProductImageElement
<qb-product-image> — a product image as a real <img>, with the URL
actually resolved.
The one element in this package that renders markup, for the same reason
React’s <ProductImage /> does: product.images[0].path is not a URL, it
is the bare storage filename, and the shop’s storage prefix that completes it
is not something a storefront credential can read. Rendering path directly
is the single most common way a headless Quickbutik shop ships broken images.
<img> and nothing around it, reusing the same node
across updates so a swapped variant does not flash. Anything you put on the
host as img-* is copied onto it (img-class, img-sizes, img-style), so
the page keeps control of the markup.
Extends
Constructors
Constructor
Returns
QbProductImageElement
Inherited from
QbElement.constructor
Properties
image
observedAttributes
Accessors
product
Get Signature
<qb-product-list> per row.
Returns
Product | null
Set Signature
Parameters
Returns
void
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbElement.attributeChangedCallback
connectedCallback()
Returns
void
Inherited from
QbElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbElement.disconnectedCallback
QbProductListElement
<qb-product-list> — a catalog grid, one <template> clone per product.
Product, plus product.priceFormatted,
product.image (the first image record) and product.href — the row’s link,
built from the href-template attribute (/products/:slug by default).
Every filter is an attribute, so a search box is list.setAttribute("search", q)
and nothing else: the previous request is aborted and only the newest answer
lands.
Extends
Constructors
Constructor
Returns
QbProductListElement
Inherited from
QbScopeElement.constructor
Properties
observedAttributes
Accessors
products
Get Signature
Returns
Product[]
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbScopeElement.attributeChangedCallback
connectedCallback()
Returns
void
Inherited from
QbScopeElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbScopeElement.disconnectedCallback
reload()
Returns
void
abstract QbScopeElement
An element that contributes to the view model its subtree is bound against.
Scopes nest by extension, never by replacement: <qb-option-values> inside a
<qb-options> row sees product, price, group and value, so a
template can read anything an ancestor offered. That is what lets the variant
picker be written without naming a single option type — the group and the
value both arrive from the product, through the scope.
Extends
Extended by
QbConsentBannerElementQbCurrencySelectElementQbOrderConfirmationElementQbProductElementQbProductListElement
Constructors
Constructor
Returns
QbScopeElement
Inherited from
QbElement.constructor
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbElement.attributeChangedCallback
connectedCallback()
Returns
void
Inherited from
QbElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbElement.disconnectedCallback
QbSeoElement
<qb-seo> — the page’s <head>, built from the product it sits next to.
<qb-product> it needs nothing else: the product comes from that
context, and the canonical from the product-path template. It writes the
title, the description, the canonical link, OpenGraph, the Twitter card and
the schema.org JSON-LD — the last being where the actual rich-result value
sits, price and availability included.
Every tag it writes is tagged data-qb-seo, and it removes its own on
update, so a soft navigation between products leaves no stale meta behind and
nothing the page itself put in <head> is touched.
A server-rendered page that already emits its head should not use this: two
sources competing for one <title> is worse than either alone. Use
buildSeo() from @quickbutik/kit in the renderer instead.
Extends
Constructors
Constructor
Returns
QbSeoElement
Inherited from
QbElement.constructor
Properties
observedAttributes
Accessors
tags
Get Signature
Returns
SeoTags
Methods
attributeChangedCallback()
Parameters
Returns
void
Inherited from
QbElement.attributeChangedCallback
connectedCallback()
Returns
void
Inherited from
QbElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbElement.disconnectedCallback
QbShopElement
<qb-shop> — an explicit shop for one subtree. Optional.
The elements do not need this. A page configured once — by the script tag’s
data-publishable-key, or by a configure() call — has an ambient shop that
every element finds on its own, and that is how a storefront should normally
be set up. Wrapping the whole page in a provider element is ceremony HTML
does not need.
What it is for is the handful of cases an ambient singleton genuinely cannot
serve:
configure():
the merchant’s GA4 / GTM / Meta ids load for this shop, gated on the
page’s consent, and a default <qb-consent-banner> is appended to the page
when it has none (privacy-policy-url and lang here are handed to it).
Inside a page whose configured shop is the same shop (a campaign
<qb-shop storefront-id>), that shop’s analytics is reused rather than
loaded twice, and this subtree’s cart reports into it.
Renders nothing and adds no markup.
Extends
Constructors
Constructor
Returns
QbShopElement
Inherited from
QbElement.constructor
Properties
observedAttributes
Accessors
cartStore
Get Signature
Returns
CartStore | null
client
Get Signature
fetch, or per-request
cookie storage.
Returns
ShopkitClient | null
Set Signature
Parameters
Returns
void
initialCart
Set Signature
Parameters
Returns
void
Methods
attributeChangedCallback()
currency and locale never rebuild the client. A rebuilt client means
a new cart store, and a currency switch must keep the same cart — it is
priced per request, so the current client is simply told the new
currency (setCurrency) and everything below refetches.
Parameters
Returns
void
Overrides
QbElement.attributeChangedCallback
connectedCallback()
Returns
void
Inherited from
QbElement.connectedCallback
disconnectedCallback()
Returns
void
Inherited from
QbElement.disconnectedCallback
Repeater
Renders a<template> once per item, in place, keyed.
Keyed matters more than it looks: a cart line whose quantity changes must
keep its existing DOM, or the <input> the shopper is typing in is replaced
mid-keystroke and loses both its caret and its focus. Rows are matched by
key, moved rather than rebuilt, and only genuinely-gone rows are removed.
The <template> is left in the DOM where the author put it — template
content does not render — and rows are appended after it, so a heading or a
“your cart is empty” paragraph written before it stays where it was.
Constructors
Constructor
Parameters
Returns
Repeater
Accessors
current
Get Signature
Returns
RepeatRow[]
hasTemplate
Get Signature
<template> to clone.
Returns
boolean
Methods
clear()
<template> itself stays.
Returns
void
render()
items.
fill is called for every surviving row as well as every new one, because
the data behind a stable key changes too — a cart line keeps its id while
its quantity and total move.
Type Parameters
Parameters
Returns
void
rowFor()
Parameters
Returns
RepeatRow | null
Interfaces
AutoBannerOptions
What the auto-mounted<qb-consent-banner> is given.
Properties
ConfigureOptions
Extends
Omit<ShopkitConfig,"consent">
Properties
Context
An opaque, comparable key for one kind of value.Type Parameters
Properties
ContextProvider
Methods
dispose()
Returns
void
update()
Returns
void
DefinedElements
WhatdefineElements registered, so a caller can see the real tag names.
Properties
DefineElementsOptions
Properties
ElementsConsentOptions
configure({ consent }) as an object: the page’s consent store options,
plus what the automatically mounted banner is given.
Extends
Properties
MoneyView
Turning state into the plain objectsdata-qb-text="…" reads.
The one thing added over what the SDK already returns is formatted money.
React’s hooks deliberately hand back { amount, currency } and let the app’s
design system format it; HTML bindings have no such escape, so every money
field appears twice: the raw minor-unit integer, and a display string.
Extended by
Properties
PriceView
Turning state into the plain objectsdata-qb-text="…" reads.
The one thing added over what the SDK already returns is formatted money.
React’s hooks deliberately hand back { amount, currency } and let the app’s
design system format it; HTML bindings have no such escape, so every money
field appears twice: the raw minor-unit integer, and a display string.
Extends
Properties
ProductContextValue
What the picker elements need from the product above them. Separate from the scope: the scope is read-only data for bindings, this is the handle<qb-option-values> uses to actually change the selection.
controller is nullable because the product is usually still loading when
the elements below first ask. They subscribe, get null, render nothing, and
are called again the moment it resolves — which is why they must be given a
value now rather than left unanswered.
Properties
Methods
addToCart()
Parameters
Returns
Promise<Cart | null>
buyNow()
<qb-buy-now> decides that. Null when nothing was started (incomplete
selection, one already in flight); throws when the handoff fails.
input may be a function, called only once the guard has passed.
Parameters
Returns
Promise<BuyNowResult | null>
canAddToCart()
Returns
boolean
RepeatRow
One rendered row: the top-level elements one<template> clone produced.
Plural because a template may legitimately have several roots (<dt> and
<dd>, two <td>s), and all of them belong to the same item.
Properties
ShopContextValue
The shop every element works against: one client, one shared cart store, and the display preferences the bindings need in order to render money as a string.Properties
VariantView
Properties
Type Aliases
ActionHandler()
Parameters
Returns
void
ContextCallback()
Type Parameters
Parameters
Returns
void
ElementsAnalyticsOptions
configure({ analytics }) and <qb-shop analytics> build the hub
from. The consent store is not an option here: the elements always use the
page’s ambient one (see consent-context.ts), unless requireConsent is
false.
Type Declaration
Scope
data-qb-text="price.formatted" is a path, not
an expression, so there is no evaluator, no new Function, and nothing a
merchant’s template can execute.
Variables
elementConstructors
productContext
scopeContext
shopContext
Functions
bindRow()
<li data-qb-text="item.productTitle"> is the obvious
way to write a one-element row. A root that is itself a scope owner is left
alone entirely; it will ask for its scope through the context protocol.
Parameters
Returns
void
bindSubtree()
host, not on host itself.
What a scope-owning element calls on itself: <qb-product> binds the markup
the author put in it, and its own attributes are configuration, not bindings.
The walk stops at nested scope owners — they run their own pass with their
own, extended scope. That is what makes <qb-option-values> inside a
<qb-options> row see both group and value.
Parameters
Returns
void
buildShopAnalytics()
requireConsent is false),
cart mutations turned into add_to_cart / remove_from_cart, and — unless
auto is false — the merchant’s own GA4 / GTM / Meta ids fetched from the
platform and added as destinations once they arrive. Events tracked before
then are remembered by the hub and delivered when they do.
Shared by configure() and <qb-shop analytics>, so a hub built for a
subtree behaves exactly like the page’s. Null when options is falsy.
Parameters
Returns
Analytics | null
cancelAutoBanner()
Returns
void
cartItemScope()
Parameters
Returns
Scope
cartScope()
<qb-cart> contributes.
Parameters
Returns
Scope
configure()
<qb-shop> unnecessary. The script-tag build calls it
automatically from its own data-* attributes, so a plain HTML page never
writes any JavaScript at all:
consent is given again.
Parameters
Returns
ShopContextValue
configureConsent()
defineElements(): an element that has already started keeps
the store it found.
Parameters
Returns
ConsentStore
createContext()
Type Parameters
Parameters
Returns
Context<T>
decorateHandoff()
<qb-checkout-button>, <qb-buy-now>, the buy-now verb — passes its
result through here before it emits qb:checkout-started or navigates, so
the URL a page sees in the event is the URL the shopper actually lands on.
The consent comes from the page’s ambient store, the requireConsent rule
from the shop’s hub; a page that configured neither, or turned consent off
(configure({ consent: false })), keeps the URL untouched (see
checkoutHandoffUrl).
Type Parameters
Parameters
Returns
T
defineElements()
@quickbutik/kit/elements
stays tree-shakeable and a bundler can drop what an app does not use. The
script-tag build calls it for you.
NotSupportedError customElements.define would otherwise throw.
Parameters
Returns
DefinedElements
delegateActions()
handlers for anything inside host.
click and change are both listened for: change is what a <select> of
option values and a quantity <input> fire, and wiring them through the same
attribute keeps one concept in the markup instead of two.
Parameters
Returns
ActionDelegate
disableAutoBanner()
configure({ consent: { banner: false } }),
data-consent-banner="false"): take down the one mounted, and refuse a
<qb-shop>’s request for another until the page asks again.
Returns
void
getAmbientConsent()
Returns
ConsentStore | null
getAmbientShop()
Returns
ShopContextValue | null
hasShop()
Returns
boolean
isConsentDisabled()
Returns
boolean
isScopeOwner()
Parameters
Returns
boolean
markScopeOwner()
Parameters
Returns
void
money()
product.currency leaves a
product page with nothing to go on but the configured currency, and with
none of those the honest options are a blank price or an unsymbolled
number. It formats the number and says so once in the console, because a
shopper seeing 1 299,00 understands it and a shopper seeing nothing does
not.
Parameters
Returns
MoneyView
optionGroupScope()
Parameters
Returns
Scope
optionValueScope()
Parameters
Returns
Scope
priceView()
Parameters
Returns
PriceView
productScope()
<qb-product> contributes.
Parameters
Returns
Scope
provideContext()
context-request events raised inside host.
produce receives the element that asked, so one provider can hand different
values to different parts of its subtree — that is how a repeated row gives
its own scope to the elements cloned into it without wrapping them in
anything. Returning undefined declines the request and lets it keep
bubbling to an outer provider.
Type Parameters
Parameters
Returns
ContextProvider
requestAutoBanner()
<qb-consent-banner> appended to
<body> once the document is parsed, unless the page already has one.
A banner the page places itself, then or later, always wins: the
auto-mounted one never duplicates it (see QbConsentBannerElement).
Requests merge rather than replace, and the page’s own configuration
outranks a <qb-shop>’s: scope: "page" (what configure() and the
script tag pass) overrides what is already set, while a shop’s request only
fills in what the page left out, and never brings back a banner the page
turned off with disableAutoBanner().
Parameters
Returns
void
requestContext()
<qb-shop> at all — the common case,
and the one the script tag is built around.
Type Parameters
Parameters
Returns
boolean
requireAmbientConsent()
Returns
ConsentStore
resetAmbientConsent()
Returns
void
resetAmbientShop()
Returns
void
resolvePath()
"product.images.0.url" against the scope. Missing anywhere → undefined,
never a throw: a template written for a product with images must not break
the page on the one product without any.
Parameters
Returns
unknown
setAmbientClient()
Parameters
Returns
ShopContextValue
setCurrency()
client.setCurrency() on the
client every element uses. Every <qb-product>, <qb-product-list> and
cart element reprices; the choice is remembered. null returns to the
configured default. Throws when nothing is configured.
Parameters
Returns
Promise<void>
stopActionWarnings()
Returns
void
variantView()
Parameters
Returns
VariantView