]> git.ipfire.org Git - thirdparty/bulma.git/commitdiff
Add carousel
authorJeremy Thomas <bbxdesign@gmail.com>
Tue, 11 Jun 2024 01:39:35 +0000 (02:39 +0100)
committerJeremy Thomas <bbxdesign@gmail.com>
Tue, 11 Jun 2024 01:39:35 +0000 (02:39 +0100)
docs/assets/javascript/shop.js
docs/shop.html

index 71002ef7d43e1ca860eb0768a2988f038e2b34b3..bcd08fd21e9beda618eec1cd1647f26cbb562042 100644 (file)
@@ -58,6 +58,22 @@ document.addEventListener("DOMContentLoaded", () => {
     };
   };
 
+  const getPreviousIndex = (list, current) => {
+    if (current === 0) {
+      return list.length - 1;
+    }
+
+    return current - 1;
+  }
+
+  const getNextIndex = (list, current) => {
+    if (current === list.length - 1) {
+      return 0;
+    }
+
+    return current + 1;
+  }
+
   const THEME_COLOR = "success";
   const STORAGE_CART_ID = "bulma-shop-cart-id";
 
@@ -366,10 +382,9 @@ document.addEventListener("DOMContentLoaded", () => {
   };
 
   const openModal = (product) => {
-    $title = $modal.querySelector(".modal-title");
-    $body = $modal.querySelector(".modal-body");
-    $buttons = $modal.querySelector(".modal .buttons");
-    $close = $modal.querySelector(".modal .buttons .button.is-close");
+    const $title = $modal.querySelector(".modal-title");
+    const $body = $modal.querySelector(".modal-body");
+    const $buttons = $modal.querySelector(".modal .buttons");
 
     $title.replaceChildren();
     buildHeading($title, product);
@@ -462,19 +477,14 @@ document.addEventListener("DOMContentLoaded", () => {
         const $option = El("", "option");
         $option.dataset.id = id;
         $option.innerText = title;
-
-        // $option.addEventListener("click", (event) => {
-        //   event.preventDefault();
-        //   product.selectedVariant = id;
-        //   update();
-        // });
+        $option.value = id;
 
         $options.appendChild($option);
       });
 
       $select.addEventListener("change", (event) => {
         event.preventDefault();
-        product.selectedVariant = id;
+        product.selectedVariant = event.target.value;
         update();
       });
 
@@ -507,7 +517,7 @@ document.addEventListener("DOMContentLoaded", () => {
     }
 
     state.products.forEach((product) => {
-      const { id, availableForSale, featuredImage } = product;
+      const { id, availableForSale, images } = product;
 
       if (!availableForSale) {
         return;
@@ -518,16 +528,51 @@ document.addEventListener("DOMContentLoaded", () => {
 
       const el = El("card-content");
 
-      const $figure = El("shop-product-image image is-square", "figure");
-      const $img = document.createElement("img");
-      $img.src = featuredImage.url;
-      $figure.appendChild($img);
-      $card.appendChild($figure);
+      const $images = El("shop-product-images image is-square");
+      const $carousel = El("shop-product-carousel image is-square");
 
-      $figure.addEventListener("click", async (event) => {
-        event.preventDefault();
-        openModal(product);
-      });
+      if (images) {
+        images.forEach(img => {
+          const $figure = El("shop-product-image image is-square", "figure");
+          const $img = document.createElement("img");
+          $img.src = img.url;
+          $figure.appendChild($img);
+          $carousel.appendChild($figure);
+        });
+
+        $images.appendChild($carousel);
+
+        if (images.length > 1) {
+          const $prev = El("shop-product-arrow shop-product-prev", "button");
+          const $prevArrow = El("icon", "button");
+          const $prevIcon = El("fa-solid fa-arrow-left", "i");
+          $prevArrow.appendChild($prevIcon);
+          $prev.appendChild($prevArrow);
+
+          $prev.addEventListener("click", event => {
+            event.preventDefault();
+            product.selectedImage = getPreviousIndex(images, product.selectedImage);
+            update();
+          });
+
+          const $next = El("shop-product-arrow shop-product-next", "button");
+          const $nextArrow = El("icon", "button");
+          const $nextIcon = El("fa-solid fa-arrow-right", "i");
+          $nextArrow.appendChild($nextIcon);
+          $next.appendChild($nextArrow);
+
+          $next.addEventListener("click", event => {
+            event.preventDefault();
+            product.selectedImage = getNextIndex(images, product.selectedImage);
+            update();
+          });
+
+          $images.appendChild($prev);
+          $images.appendChild($next);
+        }
+      }
+
+      $card.appendChild($images);
 
       buildHeading(el, product);
       buildDescription(el, product);
@@ -552,6 +597,20 @@ document.addEventListener("DOMContentLoaded", () => {
     });
   };
 
+  const updateImages = () => {
+    state.products.forEach((product) => {
+      const $blocs = document.querySelectorAll(
+        `.shop-product-${getId(product.id)}`,
+      );
+
+      $blocs.forEach(($bloc) => {
+        const $carousel = $bloc.querySelector(`.shop-product-carousel`);
+        const offset = product.selectedImage * 100;
+        $carousel.style.transform = `translateX(-${offset}%`;
+      });
+    });
+  }
+
   const updateCart = () => {
     if (isEmpty(state.cart)) {
       return;
@@ -577,13 +636,23 @@ document.addEventListener("DOMContentLoaded", () => {
         $item.dataset.id = line.id;
 
         const $left = El("media-left");
+        // const $images = El("shop-item-images");
         const $image = El("shop-item-image image is-64x64");
         const $img = El("", "img");
-
         if (product.featuredImage) {
           $img.src = product.featuredImage.url;
         }
 
+        // if (product.images) {
+        //   product.images.forEach(img => {
+        //     const $image = El("shop-item-image image is-64x64");
+        //     const $img = El("", "img");
+        //     $img.src = img.url;
+        //     $image.appendChild($img);
+        //     $images.appendChild($image);
+        //   });
+        // }
+
         $image.appendChild($img);
         $left.appendChild($image);
 
@@ -720,17 +789,17 @@ document.addEventListener("DOMContentLoaded", () => {
         `.shop-product-${getId(product.id)}`,
       );
 
-      // $blocs.forEach(($bloc) => {
-      //   const $variants = $bloc.querySelectorAll(`.variants .button`);
-
-      //   $variants.forEach(($el) => {
-      //     if ($el.dataset.id === product.selectedVariant) {
-      //       $el.classList.add(`is-${THEME_COLOR}`);
-      //     } else {
-      //       $el.classList.remove(`is-${THEME_COLOR}`);
-      //     }
-      //   });
-      // });
+      $blocs.forEach(($bloc) => {
+        const $variants = $bloc.querySelectorAll(`.shop-product-select option`);
+
+        $variants.forEach(($el) => {
+          if ($el.dataset.id === product.selectedVariant) {
+            $el.setAttribute("selected", "");
+            } else {
+            $el.removeAttribute("selected");
+          }
+        });
+      });
     });
   };
 
@@ -739,6 +808,7 @@ document.addEventListener("DOMContentLoaded", () => {
     updateCart();
     updateButtons();
     updateVariants();
+    updateImages();
   };
 
   // HTML Elements
@@ -855,6 +925,7 @@ document.addEventListener("DOMContentLoaded", () => {
       state.products = clean.products.map((product) => {
         return {
           ...product,
+          selectedImage: 0,
           selectedVariant: product.variants[0].id,
         };
       });
index 67ccfe573608e0f0b2cb199b20cf2965bb7f4173..1bce695ce118785ee0e2c87eedf2191ee5b95599 100644 (file)
@@ -235,7 +235,58 @@ breadcrumb:
     flex-direction: column;
   }
 
+  .shop-product-images {
+    position: relative;
+  }
+
+  .shop-product-images:hover .shop-product-arrow {
+    opacity: 1;
+  }
+
+  .shop-product-arrow {
+    position: absolute;
+    opacity: 0;
+    top: 0;
+    bottom: 0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 1em;
+  }
+
+  .shop-product-arrow .icon {
+    background-color: rgb(0 0 0 / 10%);
+    border-radius: 9999px;
+    transition-duration: var(--shop-duration);
+    transition-property: background-color, color, opacity;
+  }
+
+  .shop-product-arrow:hover .icon {
+    background-color: rgb(0 0 0 / 50%);
+    color: white;
+  }
+
+  .shop-product-arrow:active .icon {
+    background-color: rgb(0 0 0 / 70%);
+    color: white;
+  }
+
+  .shop-product-prev {
+    left: 0;
+  }
+
+  .shop-product-next {
+    right: 0;
+  }
+
+  .shop-product-carousel {
+    display: flex;
+    transition-duration: 300ms;
+    transition-property: transform;
+  }
+
   .shop-product-image {
+    flex-shrink: 0;
     cursor: pointer;
     overflow: hidden;
   }
@@ -246,7 +297,7 @@ breadcrumb:
     transform-origin: center;
   }
 
-  .shop-product-image:hover img {
+  .shop-product-images:hover img {
     transform: scale(1.1);
   }
 
@@ -343,29 +394,33 @@ breadcrumb:
 {% include global/header.html %}
 
 {% capture shop_placeholder %}
-<div class="shop-product is-placeholder">
+<div class="card shop-product is-placeholder">
   <figure class="shop-product-image image is-square is-skeleton">
     <img
       src="https://cdn.shopify.com/s/files/1/0837/0451/2860/files/unisex-basic-softstyle-t-shirt-white-front-6665a0551b5c8.jpg?v=1717936223"
     />
   </figure>
 
-  <div class="shop-product-heading">
-    <h3 class="shop-product-title is-skeleton">The Bulma T-Shirt</h3>
-    <div class="shop-product-price">
-      <span class="shop-price is-skeleton">$15</span>
+  <div class="card-content">
+    <div class="shop-product-heading">
+      <h3 class="shop-product-title is-skeleton">The Bulma T-Shirt</h3>
+      <div class="shop-product-price">
+        <span class="shop-price is-skeleton">$15</span>
+      </div>
     </div>
-  </div>
-  <div class="shop-product-description content">
-    <div class="shop-product-tagline content is-skeleton">
-      Show your CSS skills and add a little extra motivation with the
-      official Bulma sticker. A perfect reminder that design can be easy
-      with your favorite framework.
+
+    <div class="shop-product-description content">
+      <div class="shop-product-tagline content is-skeleton">
+        Show your CSS skills and add a little extra motivation with the
+        official Bulma sticker. A perfect reminder that design can be easy
+        with your favorite framework.
+      </div>
+    </div>
+
+    <div class="shop-product-buttons buttons">
+      <button class="button is-skeleton">Add to cart</button
+      ><button class="button is-text is-skeleton">Learn more</button>
     </div>
-  </div>
-  <div class="shop-product-buttons buttons">
-    <button class="button is-medium is-skeleton">Add to cart</button
-    ><button class="button is-text is-skeleton">Learn more</button>
   </div>
 </div>
 {% endcapture %}