Cart <mv-cart>

Kompletter Warenkorb (Drawer oder Seite): horizontale Produktzeilen mit Menge und Live-Summen, eine Leiste „Only $12.40 away from free shipping“, validierte Gutscheincodes mit Fehlermeldung (Prozent, Festbetrag oder kostenloser Versand, asynchroner Server-Hook), Ersparnis bei reduzierten Preisen, Versand, Gesamtsumme inklusive Steuern, Entfernen mit 5 Sekunden „Undo“, ein leerer Zustand und ein Button zur Bezahlung, der die Gesamtsumme zeigt.

KategorieBlöcke
TypBlock (fertige Sektion) (<mv-cart>)
Statusstabil
Installiert auchbutton, input, like-button, number-field, price, product-card, quantity, rating, progress
Keywordscart, panier, mini-cart, drawer, order-summary, promo-code, free-shipping, e-commerce, block

When to use

  • A store needs a cart drawer or cart page with live totals, quantity changes and undoable removal
  • A free-shipping progress bar and validated promo codes should encourage larger orders
  • The order summary must show savings, shipping and tax-inclusive totals before checkout

Avoid when

  • The shopper must enter address, shipping method and payment in the same flow → use Checkout instead
  • A single cart line or product summary is needed elsewhere on the page → use Product Card instead

Installation

node scripts/add.mjs cart --out ./src/marvelous

KI-Agent mit dem MCP-Server von Marvelous UI: install_components({ slugs: ["cart"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Kopierte Dateien (inklusive Abhängigkeiten): tokens/tokens.css, core/base.css, core/dismiss.js, core/dom.js, core/element.js, core/motion.js, components/cart/cart.js, components/cart/cart.css, components/button/button.css, components/input/input.css, components/like-button/like-button.js, components/like-button/like-button.css, components/number-field/number-field.js, components/number-field/number-field.css, components/price/price.js, components/price/price.css, components/product-card/product-card.js, components/product-card/product-card.css, components/quantity/quantity.js, components/quantity/quantity.css, core/form.js, components/rating/rating.js, components/rating/rating.css, components/progress/progress.css.

Verwendung

Referenz-Markup zum Starten und Anpassen mit Attributen, data-* und CSS-Variablen:

<div id="ct-demo" style="width:min(100%,64rem);margin-inline:auto;display:grid;gap:2.5rem">
  <style>
    #ct-demo .bar { display:flex; align-items:center; justify-content:space-between; gap:1rem; padding:.75rem 1rem; border:1px solid var(--mv-border); border-radius:var(--mv-radius-xl); background:var(--mv-surface) }
    #ct-demo .brand { font-weight:600; letter-spacing:.14em; text-transform:uppercase; font-size:.8125rem }
    #ct-demo .cart-btn { position:relative }
    #ct-demo .cart-btn .mv-badge { position:absolute; top:-.4rem; right:-.4rem; min-width:1.25rem; height:1.25rem; padding:0 .3rem; justify-content:center; font-size:.6875rem; border-radius:999px; font-variant-numeric:tabular-nums }
    #ct-demo h2.sec { margin:0 0 1rem; font-size:1.375rem; letter-spacing:-.01em }
    #ct-demo h2.sec small { color:var(--mv-fg-muted); font-weight:400; font-size:.875rem; margin-inline-start:.5rem }
    #ct-demo .log { margin:1rem 0 0; color:var(--mv-fg-muted); font-size:.8125rem }
    #ct-demo-drawer .mv-product-card-title a, #ct-demo .mv-product-card-title a { color:inherit; text-decoration:none }
  </style>

  <mv-dialog>
    <div class="bar">
      <span class="brand">Halcyon Home</span>
      <button class="mv-button cart-btn" data-variant="outline" data-mv-open aria-label="Open cart, 4 items"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 8h14l-1.2 12H6.2L5 8Z"/><path d="M9 8V6a3 3 0 0 1 6 0v2"/></svg> Cart <span class="mv-badge" data-mirror aria-hidden="true">4</span></button>
    </div>
    <dialog data-variant="sheet" data-side="right" id="ct-demo-drawer">
      <mv-cart free-shipping="60" shipping="4.9" shipping-label="Ground" promo-codes="WELCOME10=10%;THANKS5=5;FREESHIP=shipping" id="ct-drawer">
        <header class="mv-cart-drawer-header">
          <h2 class="mv-dialog-title">Your cart <span data-cart-count style="color:var(--mv-fg-muted);font-weight:400">4</span></h2>
          <button class="mv-dialog-close" data-mv-close aria-label="Close cart"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
        </header>
        <div class="mv-cart" data-layout="drawer">
          <div class="mv-cart-lines">
      <mv-product-card data-id="pull-merinos" data-title="Merino Crewneck Sweater" data-price="89" data-compare-at="112">
        <article class="mv-product-card" data-variant="horizontal">
          <a class="mv-product-card-media" href="#pull-merinos" tabindex="-1" aria-hidden="true"><img class="mv-product-card-image" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 500'%3E%3Cdefs%3E%3ClinearGradient id='bg' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='oklch(0.95 0.012 250)'/%3E%3Cstop offset='1' stop-color='oklch(0.87 0.025 255)'/%3E%3C/linearGradient%3E%3CradialGradient id='fl'%3E%3Cstop offset='0' stop-color='black' stop-opacity='.22'/%3E%3Cstop offset='1' stop-color='black' stop-opacity='0'/%3E%3C/radialGradient%3E%3ClinearGradient id='sh' x1='0' x2='1'%3E%3Cstop offset='0' stop-color='white' stop-opacity='.22'/%3E%3Cstop offset='.55' stop-color='white' stop-opacity='0'/%3E%3Cstop offset='1' stop-color='black' stop-opacity='.16'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='400' height='500' fill='url(%23bg)'/%3E%3Cdefs%3E%3Cpattern id='k' width='12' height='10' patternUnits='userSpaceOnUse'%3E%3Cpath d='M0 0l6 8 6-8' fill='none' stroke='black' stroke-opacity='.09' stroke-width='1.6'/%3E%3C/pattern%3E%3C/defs%3E%3Cellipse cx='200' cy='420' rx='150' ry='18' fill='url(%23fl)' opacity='1'/%3E%3Cpath d='M160 118 Q200 142 240 118 L276 128 Q300 140 310 176 L336 318 L300 331 L268 222 L267 388 Q200 397 133 388 L132 222 L100 331 L64 318 L90 176 Q100 140 124 128 Z' fill='oklch(0.34 0.05 262)'/%3E%3Cpath d='M160 118 Q200 142 240 118 L276 128 Q300 140 310 176 L336 318 L300 331 L268 222 L267 388 Q200 397 133 388 L132 222 L100 331 L64 318 L90 176 Q100 140 124 128 Z' fill='url(%23k)'/%3E%3Cpath d='M160 118 Q200 142 240 118 L276 128 Q300 140 310 176 L336 318 L300 331 L268 222 L267 388 Q200 397 133 388 L132 222 L100 331 L64 318 L90 176 Q100 140 124 128 Z' fill='url(%23sh)'/%3E%3Cpath d='M160 118 Q200 152 240 118 Q200 136 160 118Z' fill='black' fill-opacity='.22'/%3E%3Cpath d='M154 116 Q200 160 246 116' fill='none' stroke='black' stroke-opacity='.12' stroke-width='5'/%3E%3Cpath d='M133 370 Q200 379 267 370 L267 388 Q200 397 133 388 Z' fill='black' fill-opacity='.1'/%3E%3Cpath d='M64 318 L100 331 L103 316 L68 303 Z' fill='black' fill-opacity='.1'/%3E%3Cpath d='M336 318 L300 331 L297 316 L332 303 Z' fill='black' fill-opacity='.1'/%3E%3Cpath d='M132 222 L133 380 M268 222 L267 380' stroke='black' stroke-opacity='.08' stroke-width='3'/%3E%3C/svg%3E" alt=""></a>
          <div class="mv-product-card-body">
            <div class="mv-product-card-head">
              <h3 class="mv-product-card-title"><a href="#pull-merinos">Merino Crewneck Sweater</a></h3>
              <mv-price data-role="total" value="89" compare-at="112" discount="none" data-size="sm"></mv-price>
            </div>
            <p class="mv-product-card-meta">Midnight blue · Size M</p>
            <p class="mv-product-card-meta" data-role="unit" hidden>$89 each</p>
            <div class="mv-product-card-actions">
              <mv-quantity value="1" stock="3" data-size="sm" caption="none" aria-label="Quantity, Merino Crewneck Sweater"></mv-quantity>
              <button type="button" class="mv-product-card-remove" data-remove><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16M10 11v6M14 11v6M6 7l1 13h10l1-13M9 7V4h6v3"/></svg><span class="mv-product-card-remove-text">Remove</span><span class="mv-sr-only"> Merino Crewneck Sweater</span></button>
            </div>
          </div>
        </article>
      </mv-product-card>
      <mv-product-card data-id="mug-sauge" data-title="Glazed Stoneware Mug" data-price="24.9">
        <article class="mv-product-card" data-variant="horizontal">
          <a class="mv-product-card-media" href="#mug-sauge" tabindex="-1" aria-hidden="true"><img class="mv-product-card-image" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 500'%3E%3Cdefs%3E%3ClinearGradient id='bg' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='oklch(0.96 0.015 145)'/%3E%3Cstop offset='1' stop-color='oklch(0.89 0.03 150)'/%3E%3C/linearGradient%3E%3CradialGradient id='fl'%3E%3Cstop offset='0' stop-color='black' stop-opacity='.22'/%3E%3Cstop offset='1' stop-color='black' stop-opacity='0'/%3E%3C/radialGradient%3E%3ClinearGradient id='sh' x1='0' x2='1'%3E%3Cstop offset='0' stop-color='white' stop-opacity='.22'/%3E%3Cstop offset='.55' stop-color='white' stop-opacity='0'/%3E%3Cstop offset='1' stop-color='black' stop-opacity='.16'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='400' height='500' fill='url(%23bg)'/%3E%3Cellipse cx='200' cy='392' rx='130' ry='16' fill='url(%23fl)' opacity='1'/%3E%3Cpath d='M290 220 q64 0 64 60 q0 60-64 60' fill='none' stroke='oklch(0.7 0.06 150)' stroke-width='22' stroke-linecap='round'/%3E%3Cpath d='M110 170 L290 170 L284 370 Q200 392 116 370 Z' fill='oklch(0.86 0.03 75)'/%3E%3Cpath d='M110 170 L290 170 L287 270 C250 286 236 256 206 280 C176 300 150 266 113 284 Z' fill='oklch(0.7 0.06 150)'/%3E%3Cpath d='M110 170 L290 170 L284 370 Q200 392 116 370 Z' fill='url(%23sh)'/%3E%3Cellipse cx='200' cy='170' rx='90' ry='16' fill='oklch(0.36 0.05 55)'/%3E%3Cellipse cx='200' cy='170' rx='90' ry='16' fill='none' stroke='oklch(0.7 0.06 150)' stroke-width='6' style='filter:brightness(1.1)'/%3E%3C/svg%3E" alt=""></a>
          <div class="mv-product-card-body">
            <div class="mv-product-card-head">
              <h3 class="mv-product-card-title"><a href="#mug-sauge">Glazed Stoneware Mug</a></h3>
              <mv-price data-role="total" value="49.8" discount="none" data-size="sm"></mv-price>
            </div>
            <p class="mv-product-card-meta">Sage · 12 oz</p>
            <p class="mv-product-card-meta" data-role="unit">$24.90 each</p>
            <div class="mv-product-card-actions">
              <mv-quantity value="2" max="10" data-size="sm" caption="none" aria-label="Quantity, Glazed Stoneware Mug"></mv-quantity>
              <button type="button" class="mv-product-card-remove" data-remove><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16M10 11v6M14 11v6M6 7l1 13h10l1-13M9 7V4h6v3"/></svg><span class="mv-product-card-remove-text">Remove</span><span class="mv-sr-only"> Glazed Stoneware Mug</span></button>
            </div>
          </div>
        </article>
      </mv-product-card>
      <mv-product-card data-id="bougie-figuier" data-title="Fig Leaf Scented Candle" data-price="36">
        <article class="mv-product-card" data-variant="horizontal">
          <a class="mv-product-card-media" href="#bougie-figuier" tabindex="-1" aria-hidden="true"><img class="mv-product-card-image" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 500'%3E%3Cdefs%3E%3ClinearGradient id='bg' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='oklch(0.97 0.012 20)'/%3E%3Cstop offset='1' stop-color='oklch(0.9 0.03 15)'/%3E%3C/linearGradient%3E%3CradialGradient id='fl'%3E%3Cstop offset='0' stop-color='black' stop-opacity='.22'/%3E%3Cstop offset='1' stop-color='black' stop-opacity='0'/%3E%3C/radialGradient%3E%3ClinearGradient id='sh' x1='0' x2='1'%3E%3Cstop offset='0' stop-color='white' stop-opacity='.22'/%3E%3Cstop offset='.55' stop-color='white' stop-opacity='0'/%3E%3Cstop offset='1' stop-color='black' stop-opacity='.16'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='400' height='500' fill='url(%23bg)'/%3E%3Cdefs%3E%3ClinearGradient id='gls' x1='0' x2='1'%3E%3Cstop offset='0' stop-color='white' stop-opacity='.55'/%3E%3Cstop offset='.3' stop-color='white' stop-opacity='.1'/%3E%3Cstop offset='1' stop-color='white' stop-opacity='.35'/%3E%3C/linearGradient%3E%3CradialGradient id='fg'%3E%3Cstop offset='0' stop-color='oklch(0.95 0.12 90)' stop-opacity='.8'/%3E%3Cstop offset='1' stop-color='oklch(0.9 0.12 80)' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cellipse cx='200' cy='404' rx='120' ry='14' fill='url(%23fl)' opacity='1'/%3E%3Crect x='120' y='200' width='160' height='200' rx='18' fill='oklch(0.8 0.07 15)'/%3E%3Crect x='120' y='200' width='160' height='200' rx='18' fill='url(%23sh)'/%3E%3Crect x='120' y='200' width='160' height='200' rx='18' fill='url(%23gls)'/%3E%3Cellipse cx='200' cy='214' rx='72' ry='10' fill='oklch(0.95 0.02 85)'/%3E%3Cpath d='M200 214 v-18' stroke='oklch(0.25 0.01 60)' stroke-width='3'/%3E%3Crect x='144' y='270' width='112' height='70' rx='4' fill='oklch(0.97 0.01 90)'/%3E%3Ctext x='200' y='302' text-anchor='middle' font-family='Georgia,serif' font-size='18' fill='oklch(0.3 0.02 60)'%3EFig Leaf%3C/text%3E%3Ctext x='200' y='322' text-anchor='middle' font-family='Arial,sans-serif' font-size='9' letter-spacing='2' fill='oklch(0.45 0.02 60)'%3EPLANT WAX %C2%B7 6 OZ%3C/text%3E%3C/svg%3E" alt=""></a>
          <div class="mv-product-card-body">
            <div class="mv-product-card-head">
              <h3 class="mv-product-card-title"><a href="#bougie-figuier">Fig Leaf Scented Candle</a></h3>
              <mv-price data-role="total" value="36" discount="none" data-size="sm"></mv-price>
            </div>
            <p class="mv-product-card-meta">6 oz · Plant-based wax</p>
            <p class="mv-product-card-meta" data-role="unit" hidden>$36 each</p>
            <div class="mv-product-card-actions">
              <mv-quantity value="1" max="10" data-size="sm" caption="none" aria-label="Quantity, Fig Leaf Scented Candle"></mv-quantity>
              <button type="button" class="mv-product-card-remove" data-remove><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16M10 11v6M14 11v6M6 7l1 13h10l1-13M9 7V4h6v3"/></svg><span class="mv-product-card-remove-text">Remove</span><span class="mv-sr-only"> Fig Leaf Scented Candle</span></button>
            </div>
          </div>
        </article>
      </mv-product-card>
          </div>
        <div class="mv-cart-empty" hidden>
          <span class="mv-cart-empty-icon"><svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 8h14l-1.2 12H6.2L5 8Z"/><path d="M9 8V6a3 3 0 0 1 6 0v2"/></svg></span>
          <h3>Your cart is empty</h3>
          <p>Browse our new arrivals. Free shipping on orders over $60.</p>
          <a class="mv-button" href="#boutique">Shop now</a>
        </div>
          <div class="mv-cart-summary">
            <button type="button" class="mv-button mv-cart-checkout" data-checkout><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="4" y="11" width="16" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/></svg> Checkout · <span data-role="total"></span></button>
            <p class="mv-cart-note">Taxes included · Free returns within 30 days</p>
          </div>
        </div>
      </mv-cart>
    </dialog>
  </mv-dialog>

  <section aria-labelledby="ct-page-title">
    <h2 class="sec" id="ct-page-title">My cart <small>Cart page</small></h2>
    <mv-cart free-shipping="200" shipping="5.9" shipping-label="Standard, 2-4 days" tax-rate="0.2" promo-codes="WELCOME10=10%;THANKS5=5;FREESHIP=shipping" id="ct-page">
      <div class="mv-cart" data-layout="page">
        <div class="mv-cart-lines">
      <mv-product-card data-id="baskets-cuir" data-title="Pebbled Leather Sneakers" data-price="129">
        <article class="mv-product-card" data-variant="horizontal">
          <a class="mv-product-card-media" href="#baskets-cuir" tabindex="-1" aria-hidden="true"><img class="mv-product-card-image" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 500'%3E%3Cdefs%3E%3ClinearGradient id='bg' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='oklch(0.95 0.01 90)'/%3E%3Cstop offset='1' stop-color='oklch(0.87 0.02 85)'/%3E%3C/linearGradient%3E%3CradialGradient id='fl'%3E%3Cstop offset='0' stop-color='black' stop-opacity='.22'/%3E%3Cstop offset='1' stop-color='black' stop-opacity='0'/%3E%3C/radialGradient%3E%3ClinearGradient id='sh' x1='0' x2='1'%3E%3Cstop offset='0' stop-color='white' stop-opacity='.22'/%3E%3Cstop offset='.55' stop-color='white' stop-opacity='0'/%3E%3Cstop offset='1' stop-color='black' stop-opacity='.16'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='400' height='500' fill='url(%23bg)'/%3E%3Cellipse cx='200' cy='322' rx='170' ry='14' fill='url(%23fl)' opacity='1'/%3E%3Cg transform='translate(-10 10)'%3E%3Cpath d='M62 300 L358 300 C362 320 350 336 328 336 L86 336 C68 336 58 320 62 300 Z' fill='oklch(0.97 0.005 90)'/%3E%3Cpath d='M62 318 L360 318' stroke='black' stroke-opacity='.08' stroke-width='3'/%3E%3Cpath d='M68 300 C66 252 106 236 150 232 L206 198 C226 186 252 188 264 204 L292 240 C324 250 348 262 352 286 L354 300 Z' fill='oklch(0.93 0.02 90)'/%3E%3Cpath d='M68 300 C66 252 106 236 150 232 L206 198 C226 186 252 188 264 204 L292 240 C324 250 348 262 352 286 L354 300 Z' fill='url(%23sh)'/%3E%3Cpath d='M292 240 C324 250 348 262 352 286 L354 300 L318 300 C318 278 306 256 292 240Z' fill='black' fill-opacity='.08'/%3E%3Cpath d='M140 292 C184 258 236 250 306 264' fill='none' stroke='white' stroke-opacity='.85' stroke-width='9' stroke-linecap='round'/%3E%3Cpath d='M214 206 l26 36 M226 200 l26 36 M200 214 l28 34' stroke='oklch(0.97 0.005 90)' stroke-width='5' stroke-linecap='round'/%3E%3Cpath d='M206 198 C226 186 252 188 264 204' fill='none' stroke='black' stroke-opacity='.18' stroke-width='5'/%3E%3Ccircle cx='96' cy='262' r='5' fill='white' fill-opacity='.8'/%3E%3C/g%3E%3C/svg%3E" alt=""></a>
          <div class="mv-product-card-body">
            <div class="mv-product-card-head">
              <h3 class="mv-product-card-title"><a href="#baskets-cuir">Pebbled Leather Sneakers</a></h3>
              <mv-price data-role="total" value="129" discount="none" data-size="sm"></mv-price>
            </div>
            <p class="mv-product-card-meta">Ecru · Size 9</p>
            <p class="mv-product-card-meta" data-role="unit" hidden>$129 each</p>
            <div class="mv-product-card-actions">
              <mv-quantity value="1" stock="4" data-size="sm" caption="none" aria-label="Quantity, Pebbled Leather Sneakers"></mv-quantity>
              <button type="button" class="mv-product-card-remove" data-remove><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16M10 11v6M14 11v6M6 7l1 13h10l1-13M9 7V4h6v3"/></svg><span class="mv-product-card-remove-text">Remove</span><span class="mv-sr-only"> Pebbled Leather Sneakers</span></button>
            </div>
          </div>
        </article>
      </mv-product-card>
      <mv-product-card data-id="cabas-toile" data-title="Heavy Canvas Tote" data-price="45" data-compare-at="59">
        <article class="mv-product-card" data-variant="horizontal">
          <a class="mv-product-card-media" href="#cabas-toile" tabindex="-1" aria-hidden="true"><img class="mv-product-card-image" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 500'%3E%3Cdefs%3E%3ClinearGradient id='bg' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='oklch(0.97 0.02 85)'/%3E%3Cstop offset='1' stop-color='oklch(0.9 0.04 80)'/%3E%3C/linearGradient%3E%3CradialGradient id='fl'%3E%3Cstop offset='0' stop-color='black' stop-opacity='.22'/%3E%3Cstop offset='1' stop-color='black' stop-opacity='0'/%3E%3C/radialGradient%3E%3ClinearGradient id='sh' x1='0' x2='1'%3E%3Cstop offset='0' stop-color='white' stop-opacity='.22'/%3E%3Cstop offset='.55' stop-color='white' stop-opacity='0'/%3E%3Cstop offset='1' stop-color='black' stop-opacity='.16'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='400' height='500' fill='url(%23bg)'/%3E%3Cellipse cx='200' cy='418' rx='140' ry='16' fill='url(%23fl)' opacity='1'/%3E%3Cpath d='M150 170 C150 100 250 100 250 170' fill='none' stroke='oklch(0.62 0.06 60)' stroke-width='12' stroke-linecap='round'/%3E%3Cpath d='M168 172 C168 118 232 118 232 172' fill='none' stroke='oklch(0.55 0.06 60)' stroke-width='10' stroke-linecap='round'/%3E%3Cpath d='M102 170 L298 170 L318 410 Q200 420 82 410 Z' fill='oklch(0.74 0.13 75)'/%3E%3Cpath d='M102 170 L298 170 L318 410 Q200 420 82 410 Z' fill='url(%23sh)'/%3E%3Crect x='140' y='150' width='20' height='40' rx='4' fill='oklch(0.55 0.06 60)'/%3E%3Crect x='240' y='150' width='20' height='40' rx='4' fill='oklch(0.55 0.06 60)'/%3E%3Ctext x='200' y='300' text-anchor='middle' font-family='Georgia,serif' font-size='30' letter-spacing='8' fill='black' fill-opacity='.55'%3ELUMEN%3C/text%3E%3Ctext x='200' y='326' text-anchor='middle' font-family='Arial,sans-serif' font-size='10' letter-spacing='4' fill='black' fill-opacity='.45'%3EATELIER %C2%B7 PARIS%3C/text%3E%3Cpath d='M102 170 L298 170' stroke='black' stroke-opacity='.15' stroke-width='6'/%3E%3C/svg%3E" alt=""></a>
          <div class="mv-product-card-body">
            <div class="mv-product-card-head">
              <h3 class="mv-product-card-title"><a href="#cabas-toile">Heavy Canvas Tote</a></h3>
              <mv-price data-role="total" value="45" compare-at="59" discount="none" data-size="sm"></mv-price>
            </div>
            <p class="mv-product-card-meta">Ochre · Organic cotton</p>
            <p class="mv-product-card-meta" data-role="unit" hidden>$45 each</p>
            <div class="mv-product-card-actions">
              <mv-quantity value="1" max="10" data-size="sm" caption="none" aria-label="Quantity, Heavy Canvas Tote"></mv-quantity>
              <button type="button" class="mv-product-card-remove" data-remove><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16M10 11v6M14 11v6M6 7l1 13h10l1-13M9 7V4h6v3"/></svg><span class="mv-product-card-remove-text">Remove</span><span class="mv-sr-only"> Heavy Canvas Tote</span></button>
            </div>
          </div>
        </article>
      </mv-product-card>
        </div>
        <div class="mv-cart-empty" hidden>
          <span class="mv-cart-empty-icon"><svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 8h14l-1.2 12H6.2L5 8Z"/><path d="M9 8V6a3 3 0 0 1 6 0v2"/></svg></span>
          <h3>Your cart is empty</h3>
          <p>Browse our new arrivals. Free shipping on orders over $60.</p>
          <a class="mv-button" href="#boutique">Shop now</a>
        </div>
        <aside class="mv-cart-summary" data-variant="card" aria-labelledby="ct-sum-title">
          <h3 class="mv-cart-summary-title" id="ct-sum-title">Order summary</h3>
          <button type="button" class="mv-button mv-cart-checkout" data-checkout>Check out</button>
          <p class="mv-cart-note"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="4" y="11" width="16" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/></svg> Secure payment · Visa, PayPal, Apple Pay</p>
        </aside>
      </div>
    </mv-cart>
    <p class="log" id="ct-log" aria-live="polite">Try the codes WELCOME10, THANKS5 or FREESHIP.</p>
  </section>

  <section aria-labelledby="ct-empty-title">
    <h2 class="sec" id="ct-empty-title">Empty cart <small>Empty state</small></h2>
    <mv-cart>
      <div class="mv-cart" data-layout="page">
        <div class="mv-cart-lines"></div>
        <div class="mv-cart-empty">
          <span class="mv-cart-empty-icon"><svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 8h14l-1.2 12H6.2L5 8Z"/><path d="M9 8V6a3 3 0 0 1 6 0v2"/></svg></span>
          <h3>Your cart is empty</h3>
          <p>Browse our new arrivals. Free shipping on orders over $60.</p>
          <a class="mv-button" href="#boutique">Shop now</a>
        </div>
      </div>
    </mv-cart>
  </section>

  <script type="module">
    const drawer = document.getElementById("ct-drawer");
    const badge = document.querySelector("#ct-demo [data-mirror]");
    const opener = badge.closest("button");
    drawer.addEventListener("mv-change", (e) => {
      const n = e.detail.count;
      badge.textContent = n;
      opener.setAttribute("aria-label", `Open cart, ${n} item${n === 1 ? "" : "s"}`);
    });
    const log = document.getElementById("ct-log");
    const fmt = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" });
    for (const c of document.querySelectorAll("#ct-demo mv-cart")) c.addEventListener("mv-checkout", (e) => {
      e.preventDefault();
      log.textContent = `mv-checkout: ${e.detail.count} item(s), total ${fmt.format(e.detail.total)}`;
    });
  </script>
</div>

API

Attributes

NameTypDefaultDescription
currency / localestringUSD / en-USAmount formatting (Intl.NumberFormat).
free-shippingnumberFree-shipping threshold (after discounts): turns on the progress bar.
shippingnumber0Shipping cost below the threshold.
shipping-labelstringShipping method shown (“Shipping · Ground”).
tax-ratenumberIncluded tax rate (0.2): adds an “Includes tax (20%)” row.
promo-codesstringClient-side accepted codes: “WELCOME10=10%;THANKS5=5;FREESHIP=shipping”. Shows the promo code field.
promobooleanShows the promo code field without local codes (use with validatePromo).
undonumber5000Delay (ms) during which a removal can be undone.
data-layoutpage | drawerOn .mv-cart: page (lines + summary that sticks beyond a 46rem container) or drawer (scrolling lines, fixed footer).
data-variantcardOn .mv-cart-summary: summary as a card; on .mv-cart-lines: compact (no dividers).

Properties

NameTypDescription
linesMvProductCard[]Active lines (excluding pending removals).
totalsobject{ count, subtotal, original, savings, discount, shipping, freeByThreshold, total, tax, promo }.
validatePromo(code, totals) => Promise<{ ok, type, value, label?, message? }>Server-side code validation; type percent (0.1), amount or shipping.

Methods

NameDescription
applyPromo(code)Validates and applies a code; resolves { ok, message }.
removePromo()Removes the applied code.

Events

NameDescription
mv-changedetail: totals, on every quantity change, removal, undo or code.
mv-promodetail: { code, applied, type, value }.
mv-checkoutClick on [data-checkout]; cancelable; detail: totals.

Content structure

NameDescription
.mv-cart > .mv-cart-linesmv-product-card lines (data-price, data-compare-at, mv-quantity, [data-remove]).
.mv-cart-summarySummary: generated totals, promo code and bar, [data-checkout] (its [data-role=total] receives the total), .mv-cart-note.
.mv-cart-emptyEmpty state, shown when no lines are left.
[data-cart-count]Any element inside mv-cart: receives the item count.

CSS classes

NameDescription
mv-cart / -lines / -summary / -summary-title / -progress / -totals / -row / -total / -promo / -promo-message / -undo / -checkout / -note / -empty / -empty-icon / -drawer-headerStructure.

Accessibility

Totals in a description list (<dl>). Removal: the line is hidden and replaced by “… was removed. Undo”, which takes focus; announced via role=status; focus returns to the quantity after undo. Promo code: labeled field, aria-live message linked with aria-describedby, aria-invalid on error, aria-busy button while verifying; the code is removed with a button named “Remove code …”. Sale prices are announced as “instead of”. The shipping bar is decorative; the text carries the information.

Diese Seite wurde mit KI übersetzt. Übersetzungsfehler melden