window.Luxe.cart and events
Place widgets in the Luxe cart drawer and react to what Luxe does. Display only: never a price, never billing data.
Getting the cart object
window.Luxe.cart exists as soon as luxe-root.js runs on a store that uses the Luxe cart drawer (with the theme's own cart it is undefined); register and hideLines calls made before the drawer loads are queued. Your script may run first:
function withLuxeCart(fn) {
if (window.Luxe?.cart) fn(window.Luxe.cart);
else document.addEventListener("luxe:ready", () => { if (window.Luxe?.cart) fn(window.Luxe.cart); }, { once: true });
}Members
| Member | Signature | What it does |
|---|---|---|
register | (zone, renderer) => unregister | mount(host, ctx) once, update?(ctx) after each cart read, unmount?() on unregister |
hideLines | (predicate) => void | Keeps matching lines out of the list and count; they stay in every total |
refresh | () => void | Reads /cart.js once |
withLuxeCart((cart) => {
const unregister = cart.register("checkout-before", {
mount(host, ctx) {
host.innerHTML = '<label><input type="checkbox"> Plant a tree (+' + ctx.money(100) + ')</label>';
},
update(ctx) {
/* ctx.cart is Shopify's /cart.js object */
},
});
});withLuxeCart((cart) => {
// Keep a donation line out of the drawer list; it stays in the totals.
cart.hideLines((line) => line.product_type === "Donation");
});// After changing the cart through the Storefront API:
window.Luxe?.cart?.refresh();
// or
document.dispatchEvent(new CustomEvent("luxe:cart:request-refresh"));ctx is { cart, money(cents), locale }.
Zones and hosts
| Zone | Where |
|---|---|
top | Below the header |
lines-after | Below the last line |
checkout-before | Above the subtotal |
checkout-after | Under the checkout button |
empty | In place of the lines on an empty bag |
Each widget gets a light-DOM host inside <luxe-cart-drawer> with data-luxe-slot, styled by your CSS. Hosts are never re-created. #luxe-checkout-anchor is a stable anchor inside the Route host, for Route's Checkout Button Selector.
Events
Every luxe:* event is dispatched on document and is cancelable.
| Event | When | Detail |
|---|---|---|
luxe:ready | Runtime configured | { version } |
luxe:cart:updated | After every cart read | { itemCount, totalPrice, lines }; lines is a string, "key:quantity,…" |
luxe:kit:added | A set was added; with the theme's own cart, preventDefault() keeps the shopper on the page | { kitId, source } |
luxe:drawer:open, close | Luxe drawer only | { source } on open |
luxe:drawer:rendered | After every render | { slots } |
luxe:offer:shown, accepted, declined | Checkout offer | { offerId, placement }, { offerId, variantIds }, { offerId }: ids only, never prices or shopper data |
luxe:warning | Theme editor only | { element, message } |
Listened for
| Event | Effect |
|---|---|
luxe:drawer:request-open | Opens the drawer |
luxe:cart:request-refresh | Reads the cart once |
B2B buyers
For company buyers with B2B buyers on (the default), no Luxe script loads and window.Luxe.b2b is true. Check window.Luxe?.cart first.
Rules
- Keep optional charges opt-in. Luxe never changes another app's line.
- Exclude protection, donations or memberships from the ladder with Excluded products, not a line property.