CartistoDocs

Components

The cartisto-* custom elements — platform-rendered UI you place and style.

When the platform renders the UI itself, it ships a custom element. You place the tag; the platform renders and binds it. Every platform element has one canonical cartisto-* name.

Components render light DOM with familiar class names and layer their base CSS in @layer cartisto, so your unlayered theme CSS always wins — you restyle without !important.

Catalog

Element What it does
<cartisto-add-to-cart product-id="…" [has-variants] [out-of-stock]> Wraps your own <button> via display:contents — you keep the look, it owns add-to-cart.
<cartisto-wishlist product-id="…"> Same pattern for wishlist toggling; sets aria-pressed.
<cartisto-bundles> Renders all offer types (Mix & Match, BOGO, free gift, …) from platform-seeded data.
<cartisto-auth-modal> Auto-mounted login/register modal; opens on gated actions or ?auth=.
<cartisto-cart-drawer> Auto-mounted slide-in cart; opens via [data-cartisto="cart-trigger"].
<cartisto-quantity min max> Quantity stepper; emits cartisto:quantity:change, exposes .value.
<cartisto-toast> Toast host; cartisto.showNotification(...) routes through it.
<cartisto-modal> Accessible modal primitive; cartisto.modal.confirm(...).

Enhancing your own button

<cartisto-add-to-cart> and <cartisto-wishlist> don’t render a button — they enhance yours, so your styling is untouched:

<cartisto-add-to-cart product-id="{{ product.id }}"
  product-url="{{ '/products/' | append: product.slug | lang_path }}"
  {% if product.hasVariants %}has-variants{% endif %}
  {% if product.quantity <= 0 %}out-of-stock{% endif %}>
  <button class="my-btn my-btn--primary">{{ 'product.addToCart' | t }}</button>
</cartisto-add-to-cart>

Add out-of-stock and it won’t add to cart; add has-variants (with a product-url) and it sends the shopper to the product page to pick a variant instead of adding directly.

Placing a platform-rendered widget

{# offers on the product page — data is seeded by the platform #}
<cartisto-bundles></cartisto-bundles>

{# a cart trigger anywhere in your header #}
<button data-cartisto="cart-trigger" aria-label="Cart">🛒</button>

The one theme-owned element

<product-card> is not prefixed and is theme-owned — the card is your look, so you render its markup. It’s the deliberate exception to the “shared component” rule.

Note

Adding a component is a platform job The component catalog is first-party. A shared interactive widget belongs in the platform component library — never copied per theme. That’s what keeps a feature O(1) instead of O(themes).