Open it.
Quantities and removals run through a simulated
updateCartItem(), delay and all.
- Items
- 0
- Subtotal
- $0.00
Two ways to draw a line.
By default the panel renders line items from a JS template. Point
section at a Shopify section and the server renders them instead — same
selectors, same events, same states, and the markup rides along in the mutation
response. Add optimistic and quantities move on the click, not on the
answer.
- Lines drawn by
- JS template
- Requests in flight
- 0
<!-- server renders content, JS renders behavior -->
<cart-panel section="API-cart-items" optimistic>
One line, whole cart.
Panel and item are designed as a set, so the root import registers both. Take them à la carte if you'd rather — the panel alone still renders count, subtotal and empty state, it just skips the items.
// <cart-panel>, <cart-item>, <cart-item-content>, <cart-item-processing>
import '@magic-spells/cart-panel';
import '@magic-spells/cart-panel/css';
// à la carte
import '@magic-spells/cart-panel/panel';
import '@magic-spells/cart-panel/cart-item';
It doesn't work alone.
Two sibling packages sit inside the panel and listen to
cart-panel:data-changed: a shipping bar that fills to $150, and a gift that
adds itself to the cart at $200 and takes itself back out below it. Open the cart and add
items.
import '@magic-spells/cart-panel';
import '@magic-spells/cart-progress-bar';
import '@magic-spells/gift-with-purchase';
Everything announces.
The full reference.
Panel attributes
manualrefreshCart() yourself.sectionoptimistichide-count-when-empty[data-content-cart-count] element, page-wide, while the cart
is empty.
statehas-items or empty. Drives
[data-cart-has-items] and [data-cart-is-empty].
Panel methods
show(trigger?, cart?)<dialog-panel> ancestor.hide()[data-action-hide-cart].getCart()/cart.json. Override it to fake the cart — this demo fakes the
endpoint instead.
getCartSection()/?sections=<id> in section mode. Resolves to
null without one.
updateCartItem(key, qty)/cart/change.json. qty: 0 removes. In section mode it
asks for the markup too.
refreshCart(cart?)setCartItemTemplate(name, fn)_cart_template, else default.
setCartItemProcessingTemplate(fn)on(event, fn) / off()Panel events
cart-panel:show{ triggerElement }show().cart-panel:hidehide().cart-panel:refreshed{ cart }cart-panel:updated{ cart }cart-panel:data-changedcalculated_count, calculated_subtotal
cart-panel:error{ key, error }Selectors
[data-content-cart-items][data-cart-has-items][data-cart-is-empty]
state.[data-content-cart-count][data-content-cart-subtotal]
[data-action-hide-cart][data-action-remove-item][data-cart-quantity][data-content-line-price]
Line item properties
_hide_in_cart_ignore_price_in_subtotalcalculated_subtotal._cart_template_group_id / _group_roleCart item
CartItem.setTemplate()CartItem.setProcessingTemplate()CartItem.createAnimated()
setState() · setData() · destroyYourself()
setContent(html)applyItemData(item)
ready · processing · destroying ·
appearing
state attribute. Blur, scale and height come from CSS.cart-item:removecart-item:quantity-change
CSS custom properties
--cart-item-loader-color#000--cart-item-processing-duration--cart-item-destroying-duration--cart-item-appearing-duration
250ms · 600ms · 400ms--cart-item-processing-scale--cart-item-destroying-scale
0.98 · 0.85--cart-item-processing-blur--cart-item-destroying-blur
1px · 10px--cart-item-shadow-colorrgba(0, 0, 0, 0.15)