From 957cf79e45a145d15d2052fe30a3ec91ade9419c Mon Sep 17 00:00:00 2001 From: isUnknown Date: Wed, 14 Jan 2026 12:06:26 +0100 Subject: [PATCH] Add cart button to header with item count Add a cart button in the header (right of language switcher) that displays the number of items in parentheses when cart is not empty. Button opens the cart drawer on click and count updates dynamically when items are added/removed. Co-Authored-By: Claude Sonnet 4.5 --- assets/css/partials/_site-header.scss | 45 +++++++++++++++++++++++++-- assets/js/cart-drawer.js | 29 +++++++++++++++++ site/snippets/header.php | 4 +++ 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/assets/css/partials/_site-header.scss b/assets/css/partials/_site-header.scss index cf92821..f74bf25 100644 --- a/assets/css/partials/_site-header.scss +++ b/assets/css/partials/_site-header.scss @@ -43,14 +43,20 @@ } } - .header-left, - .header-right { + .header-left { width: 90px; display: flex; align-items: center; justify-content: flex-end; } + .header-right { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 1rem; + } + .header-center { display: flex; flex-direction: column; @@ -75,4 +81,39 @@ color: var(--color-txt); } } + + .header-cart-btn { + background: none; + border: none; + cursor: pointer; + font-size: 0.875rem; + text-transform: uppercase; + color: var(--color-txt); + padding: 0; + line-height: 1; + display: flex; + align-items: center; + gap: 0.25rem; + transition: opacity 0.2s; + + &:hover { + opacity: 0.7; + } + } + + .header-cart-count { + font-weight: normal; + + &:empty { + display: none; + } + + &:not(:empty)::before { + content: '('; + } + + &:not(:empty)::after { + content: ')'; + } + } } diff --git a/assets/js/cart-drawer.js b/assets/js/cart-drawer.js index 5849190..95972c1 100644 --- a/assets/js/cart-drawer.js +++ b/assets/js/cart-drawer.js @@ -9,6 +9,8 @@ const checkoutBtn = document.querySelector('[data-cart-checkout]'); const closeButtons = document.querySelectorAll('[data-cart-close]'); const totalDisplay = document.querySelector('[data-cart-total]'); + const headerCartBtn = document.querySelector('[data-cart-open]'); + const headerCartCount = document.querySelector('[data-cart-count]'); // Get translated text const removeText = drawer.dataset.textRemove || 'Remove'; @@ -38,6 +40,11 @@ btn.addEventListener('click', closeDrawer); }); + // Open drawer from header button + if (headerCartBtn) { + headerCartBtn.addEventListener('click', openDrawer); + } + // Checkout button checkoutBtn.addEventListener('click', () => { if (currentCart?.checkoutUrl) { @@ -81,6 +88,24 @@ }).format(amount); } + function updateCartCount() { + if (!currentCart || !currentCart.lines || currentCart.lines.edges.length === 0) { + if (headerCartCount) { + headerCartCount.textContent = ''; + } + return; + } + + // Calculate total quantity + const totalQty = currentCart.lines.edges.reduce((sum, edge) => { + return sum + edge.node.quantity; + }, 0); + + if (headerCartCount) { + headerCartCount.textContent = totalQty > 0 ? totalQty : ''; + } + } + function renderCart() { if (!currentCart || !currentCart.lines || currentCart.lines.edges.length === 0) { emptyState.classList.remove('hidden'); @@ -89,6 +114,7 @@ if (totalDisplay) { totalDisplay.textContent = '0,00 €'; } + updateCartCount(); return; } @@ -103,6 +129,9 @@ totalDisplay.textContent = formatPrice(total, currency); } + // Update header cart count + updateCartCount(); + // Render cart items itemsContainer.innerHTML = currentCart.lines.edges.map(edge => { const item = edge.node; diff --git a/site/snippets/header.php b/site/snippets/header.php index ee74be4..57257c8 100644 --- a/site/snippets/header.php +++ b/site/snippets/header.php @@ -47,5 +47,9 @@ + +