diff --git a/snippets/card-gallery.liquid b/snippets/card-gallery.liquid new file mode 100644 index 0000000..eef50c3 --- /dev/null +++ b/snippets/card-gallery.liquid @@ -0,0 +1,488 @@ +{%- doc -%} + Displays product images in a carousel. + Settings allow for a full slideshow, showing only the first image, or showing the second image when hovering. + Note: When the product card itself is in a carousel layout, the card-gallery's carousel is disabled with JavaScript. + + @param [children] - Additional content rendered below the card gallery + @param [section] - The section object the snippet is rendered in + @param [block] - The block object the snippet is rendered in +{%- enddoc -%} + +{% liquid + assign product = closest.product + assign block_settings = block.settings + assign image_sizes = '(min-width: 750px) 50vw, 100vw' + + # Check if product has badges and determine position + assign has_badges = false + assign badge_position = null + if product != blank + comment + start Yagi + endcomment + assign product_compare_at_price = product.compare_at_price + assign product_price = product.price + + assign product_price = product.metafields.app--168074346497.min_auto_discounted_price.value | default: product.price + + if product.metafields.app--168074346497.discount_percentage.value > 0.01 + assign deducted_percentage = 1.0 | minus: product.metafields.app--168074346497.discount_percentage.value + + assign product_price = product.price | divided_by: 100.0 | times: deducted_percentage | times: 100.0 | ceil + + assign product_compare_at_price = product.price + + if product.compare_at_price > product_compare_at_price + assign product_compare_at_price = product.compare_at_price + endif + endif + comment + end Yagi + endcomment + + if product.available == false or product_compare_at_price > product_price + assign has_badges = true + assign badge_position = settings.badge_position + endif + endif + + # if the card-gallery has a section.settings.product_card_size: + # assume grid-template autofill(card-size, 1fr) and calculate the sizes attribute based on the minimum card size + # + # if section has section.settings.columns: + # assume grid-template repeat(column-count, 1fr) and calculate the sizes attribute based on the number of columns + if section.settings.product_card_size + assign mobile_image_size = '100vw' + if section.settings.mobile_product_card_size == 'small' + assign mobile_image_size = '50vw' + endif + + capture card_size + render 'util-product-grid-card-size', section: section + endcapture + assign card_size = card_size | strip | replace: 'px', '' | plus: 0 + capture sizes_attribute + render 'util-autofill-img-size-attr', card_size: card_size, card_gap: section.settings.columns_gap_horizontal, mobile_size: mobile_image_size + endcapture + assign image_sizes = sizes_attribute | strip + elsif section.settings.columns and section.settings.layout_type != 'editorial' + assign viewport_width = 100.0 | divided_by: section.settings.columns + assign sizes_attribute = '(min-width: 750px) [viewport_width]vw, 100vw' | replace: '[viewport_width]', viewport_width + assign image_sizes = sizes_attribute | strip + endif + + assign ratio = '1' + case block_settings.image_ratio + when 'landscape' + assign ratio = '16 / 9' + when 'portrait' + assign ratio = '4 / 5' + when 'square' + assign ratio = '1' + when 'adapt' + assign ratio = product.featured_media.preview_image.aspect_ratio | default: '1' + endcase + + if block_settings.image_ratio == 'adapt' and block_settings.constrain_to_viewport + if block_settings.constrain_to_viewport != '' + assign constrain_to_viewport = true + assign media_fit = block_settings.constrain_to_viewport + endif + endif +%} + + + +{% render 'slideshow-styles' %} +{% render 'product-media-container-styles' %} + +{% stylesheet %} + .card-gallery { + position: relative; + overflow: hidden; + container-type: inline-size; /* Make card-gallery a container */ + container-name: card-gallery-container; /* Optional: name the container */ + } + + @container (max-width: 70px) { + .card-gallery:hover .quick-add__button { + display: none; + } + } + + .card-gallery__placeholder svg { + height: 100%; + width: 100%; + } + + .card-gallery svg { + aspect-ratio: var(--gallery-aspect-ratio, var(--ratio)); + } + + .product-card-gallery__title-placeholder { + padding: var(--padding-md); + font-size: var(--font-size--2xl); + line-height: var(--line-height--display-loose); + word-break: break-word; + color: var(--color-foreground); + background-color: rgb(var(--color-foreground-rgb) / var(--opacity-5)); + aspect-ratio: var(--gallery-aspect-ratio); + border-radius: var(--product-corner-radius); + display: block; + } + + .product-card-gallery__title-placeholder .title-text { + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 5; + line-clamp: 5; + overflow: hidden; + } + + .card-gallery[data-image-ratio='landscape'] .product-card-gallery__title-placeholder .title-text { + -webkit-line-clamp: 3; + line-clamp: 3; + } + + @media screen and (min-width: 750px) { + .product-grid[data-product-card-size='extra-large'] .product-card-gallery__title-placeholder { + padding: var(--padding-3xl); + font-size: var(--font-size--3xl); + } + + .product-grid[data-product-card-size='large'] .product-card-gallery__title-placeholder { + padding: var(--padding-2xl); + font-size: var(--font-size--2xl); + } + + .product-grid[data-product-card-size='medium'] .product-card-gallery__title-placeholder { + padding: var(--padding-xl); + font-size: var(--font-size--xl); + } + + .product-grid[data-product-card-size='small'] .product-card-gallery__title-placeholder { + padding: var(--padding-sm); + font-size: var(--font-size--lg); + } + + .product-grid[data-product-card-size='extra-large'] + .card-gallery.card-gallery--badge-top-right + .product-card-gallery__title-placeholder { + padding-inline-end: calc(var(--padding-3xl) + 50px); + } + + .product-grid[data-product-card-size='large'] + .card-gallery.card-gallery--badge-top-right + .product-card-gallery__title-placeholder { + padding-inline-end: calc(var(--padding-2xl) + 50px); + } + + .product-grid[data-product-card-size='medium'] + .card-gallery.card-gallery--badge-top-right + .product-card-gallery__title-placeholder { + padding-inline-end: calc(var(--padding-xl) + 50px); + } + + .product-grid[data-product-card-size='small'] + .card-gallery.card-gallery--badge-top-right + .product-card-gallery__title-placeholder { + padding-inline-end: calc(var(--padding-sm) + 50px); + } + + .product-grid[data-product-card-size='extra-large'] + .card-gallery.card-gallery--badge-top-left + .product-card-gallery__title-placeholder { + padding-top: calc(var(--padding-3xl) + 40px); + } + + .product-grid[data-product-card-size='large'] + .card-gallery.card-gallery--badge-top-left + .product-card-gallery__title-placeholder { + padding-top: calc(var(--padding-2xl) + 40px); + } + + .product-grid[data-product-card-size='medium'] + .card-gallery.card-gallery--badge-top-left + .product-card-gallery__title-placeholder { + padding-top: calc(var(--padding-xl) + 40px); + } + + .product-grid[data-product-card-size='small'] + .card-gallery.card-gallery--badge-top-left + .product-card-gallery__title-placeholder { + padding-top: calc(var(--padding-sm) + 40px); + } + + .product-grid[data-product-card-size='extra-large'] + .card-gallery.card-gallery--badge-bottom-left + .product-card-gallery__title-placeholder { + padding-bottom: calc(var(--padding-3xl) + 40px); + } + + .product-grid[data-product-card-size='large'] + .card-gallery.card-gallery--badge-bottom-left + .product-card-gallery__title-placeholder { + padding-bottom: calc(var(--padding-2xl) + 40px); + } + + .product-grid[data-product-card-size='medium'] + .card-gallery.card-gallery--badge-bottom-left + .product-card-gallery__title-placeholder { + padding-bottom: calc(var(--padding-xl) + 40px); + } + + .product-grid[data-product-card-size='small'] + .card-gallery.card-gallery--badge-bottom-left + .product-card-gallery__title-placeholder { + padding-bottom: calc(var(--padding-sm) + 40px); + } + } + + @media screen and (max-width: 749px) { + .product-card-gallery__title-placeholder { + font-size: var(--font-size--xl); + padding: var(--padding-md); + } + + .product-grid[data-product-card-size] + .card-gallery.card-gallery--badge-top-right + .product-card-gallery__title-placeholder { + padding-inline-end: calc(var(--padding-sm) + 50px); + } + + .product-grid[data-product-card-size] + .card-gallery.card-gallery--badge-top-left + .product-card-gallery__title-placeholder { + padding-top: calc(var(--padding-sm) + 40px); + } + + .product-grid[data-product-card-size] + .card-gallery.card-gallery--badge-bottom-left + .product-card-gallery__title-placeholder { + padding-bottom: calc(var(--padding-sm) + 40px); + } + } + + [product-grid-view='zoom-out'] .card-gallery .product-card-gallery__title-placeholder { + /* stylelint-disable-next-line declaration-no-important */ + padding: var(--padding-xs) !important; + font-size: var(--font-size--xs); + } + + [product-grid-view='zoom-out'] .card-gallery .slideshow-control { + min-width: auto; + } + + ul[product-grid-view='zoom-out'] .product-grid__card .card-gallery { + display: block; + } + + [product-grid-view='zoom-out'] + .card-gallery + > :is(quick-add-component, .product-badges, slideshow-component > slideshow-controls) { + display: none; + } + + ul[product-grid-view='zoom-out'] .card-gallery > img { + display: block; + } + + .card-gallery slideshow-arrows .slideshow-control { + /* Align icons with quick-add button */ + padding-inline: var(--padding-xl); + + @container (max-width: 249px) { + padding-inline: 0 var(--padding-sm); + + [dir='rtl'] & { + padding-inline: var(--padding-sm) 0; + } + } + } + + /* + * Card galleries preview the next or previous images on 'pointerenter', so we + * try to kick load them beforehand (they are lazy loaded otherwise). + */ + .card-gallery + :is( + slideshow-slide:has(+ slideshow-slide[aria-hidden='false']), + slideshow-slide[aria-hidden='false'] + slideshow-slide + ) { + content-visibility: auto; + + slideshow-component[actioned] & { + content-visibility: visible; + } + } +{% endstylesheet %}