Created
January 14, 2025 22:28
-
-
Save odessy/69f5df30e7d2a55b8de00fe021f86c93 to your computer and use it in GitHub Desktop.
Swatches limit pipeline
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- /snippets/product-grid-item-variant.liquid --> | |
{% comment %} | |
A grid item for products used in collection grid view | |
* product {object} - The current prodcut | |
{% render 'product-grid-item', product: product %} | |
{% endcomment %} | |
{%- liquid | |
assign on_sale = false | |
if product.compare_at_price > product.price | |
assign on_sale = true | |
endif | |
assign sold_out = true | |
if product.available | |
assign sold_out = false | |
endif | |
comment | |
Siblings are a collection metafield called theme.siblings | |
endcomment | |
assign sibs_collection = nil | |
assign has_siblings = false | |
if settings.show_siblings and product.metafields.theme.siblings.value != blank and product.metafields.theme.siblings.type == 'single_line_text_field' | |
assign sibs_collection = collections[product.metafields.theme.siblings.value] | |
comment | |
Ensure the collection was set up to contain this product | |
endcomment | |
for sib_product in sibs_collection.products | |
if sib_product == product | |
assign has_siblings = true | |
endif | |
endfor | |
endif | |
comment | |
Swatches are generated by matching a list of comma separated translations | |
endcomment | |
assign swatch_option = nil | |
assign has_swatches = false | |
if settings.swatches_enable and settings.swatches_collection_enable | |
assign swatch_translation = 'general.swatches.color' | t | |
assign swatch_labels = swatch_translation | append: ',' | split: ',' | |
for label in swatch_labels | |
assign sanitized_label = label | lstrip | rstrip | |
if product.options_by_name[sanitized_label].values.size > 0 | |
assign has_swatches = true | |
assign swatch_option = product.options_by_name[sanitized_label] | |
break | |
endif | |
endfor | |
endif | |
comment | |
A button that will add to cart immediately: product with only one default variant or a product with color swatches and no other variants | |
endcomment | |
assign instant_add_button = nil | |
if settings.instant_add_enable | |
if product.variants.size == 1 | |
assign instant_add_button = true | |
elsif has_swatches and product.options.size == 1 | |
assign instant_add_button = true | |
endif | |
endif | |
comment | |
A quick add button that will show short variants like 'size' inside the button. | |
endcomment | |
assign inline_variant_buttons = nil | |
comment | |
Get the non color option | |
swatch_option.position -> 1 is off by one, it means product.options[0] | |
In case of siblings, the inline option buttons always use the first option | |
endcomment | |
if settings.instant_add_enable | |
if product.options.size == 1 | |
assign inline_variant_buttons = product.options_with_values[0] | |
elsif has_swatches and product.options.size == 2 | |
if swatch_option.position == 1 | |
assign inline_variant_buttons = product.options_with_values[1] | |
else | |
assign inline_variant_buttons = product.options_with_values[0] | |
endif | |
endif | |
endif | |
comment | |
Capture the swatch link markup so we only have filter product.variants by color one time | |
endcomment | |
assign swatch_link_markup = '' | |
comment | |
Pass pre-filtered color variants into content, because the logic needs to know about | |
swatch option positions and swatches need to use the where filter to get the list | |
endcomment | |
assign inline_variants = nil | |
# Placeholder to be displayed when no product image | |
assign placeholder = placeholder | default: false | |
-%} | |
<product-grid-item | |
aria-label="{{ product.title | strip_html | escape }}" | |
class="product-grid-item group/product-grid-item" | |
data-item-id="{{ product.id }}" | |
> | |
{% if has_siblings and sibs_collection.products.size > 0 %} | |
{%- for sib_product in sibs_collection.products limit: 50 -%} | |
{% liquid | |
assign visible = false | |
assign first_sibling_variant = sib_product.variants[0] | |
if sib_product.id == product.id | |
assign visible = true | |
endif | |
if visible and preload | |
assign preload_variant = true | |
endif | |
if visible and eagerload | |
assign eagerload_variant = true | |
endif | |
assign inline_variant_buttons = nil | |
if settings.instant_add_enable and sib_product.options.size == 1 | |
assign inline_variant_buttons = sib_product.options_with_values[0] | |
endif | |
if inline_variant_buttons | |
assign inline_variants = sib_product.variants | |
endif | |
-%} | |
{% render 'product-grid-item-variant', | |
product: sib_product, | |
variant: first_sibling_variant, | |
badge_string: badge_string, | |
visible: visible, | |
instant_add_button: instant_add_button, | |
inline_variant_buttons: inline_variant_buttons, | |
inline_variants: inline_variants, | |
section_width: section_width, | |
eagerload: eagerload_variant, | |
preload: preload_variant, | |
placeholder: placeholder, | |
columns_desktop: columns_desktop, | |
columns_tablet: columns_tablet, | |
columns_mobile: columns_mobile | |
%} | |
{% endfor %} | |
{% elsif has_swatches %} | |
{%- assign swatch_position_key = 'option' | append: swatch_option.position -%} | |
{%- assign swatch_limit = swatch_option.values.size | at_most: 5 -%} | |
{%- assign swatch_limit_plus = swatch_option.values.size | minus: swatch_limit -%} | |
{%- assign found_visible = false -%} | |
{%- for lo_color_swatch_name in swatch_option.values limit: swatch_limit -%} | |
{% liquid | |
assign color_swatch_name = lo_color_swatch_name | |
assign this_color_variants = product.variants | where: swatch_position_key, color_swatch_name | |
assign in_stock_options = this_color_variants | where: 'available' | |
assign visible = false | |
# By default, show the first color variant | |
assign current_variant = this_color_variants | first | |
# Try to find a variant that has a featured media | |
for color_variant in this_color_variants | |
if color_variant.featured_media | |
assign current_variant = color_variant | |
break | |
endif | |
endfor | |
if inline_variant_buttons | |
assign inline_variants = this_color_variants | |
endif | |
# If there is a variant selected from filters, show that variant first | |
if product.selected_variant | |
assign selected_color_variant = this_color_variants | where: 'id', product.selected_variant.id | first | |
if selected_color_variant | |
assign visible = true | |
assign found_visible = true | |
endif | |
elsif forloop.first | |
assign visible = true | |
assign found_visible = true | |
endif | |
# If last loop run ensure the selected variant is last if available | |
if found_visible == false and forloop.last | |
if product.selected_variant | |
assign current_variant = product.selected_variant | |
assign current_position = swatch_option.position | minus: 1 | |
assign color_swatch_name = current_variant.options[current_position] | |
endif | |
assign visible = true | |
endif | |
if visible and preload | |
assign preload_variant = true | |
endif | |
if visible and eagerload | |
assign eagerload_variant = true | |
endif | |
-%} | |
{% render 'product-grid-item-variant', | |
product: product, | |
variant: current_variant, | |
badge_string: badge_string, | |
visible: visible, | |
instant_add_button: instant_add_button, | |
inline_variant_buttons: inline_variant_buttons, | |
inline_variants: inline_variants, | |
section_width: section_width, | |
swatch_option: swatch_option, | |
eagerload: eagerload_variant, | |
preload: preload_variant, | |
placeholder: placeholder, | |
columns_desktop: columns_desktop, | |
columns_tablet: columns_tablet, | |
columns_mobile: columns_mobile | |
%} | |
{% capture swatch_link_markup %} | |
{{ swatch_link_markup }} | |
<radio-swatch class="swatch__button{% if in_stock_options.size == 0 %} sold-out{% endif %}{% if settings.swatches_squares %} swatch__button--square{% endif %}"> | |
<a | |
href="{{ current_variant.url }}" | |
class="swatch__label" | |
data-swatch="{{ color_swatch_name }}" | |
data-grid-item-variant="{{ current_variant.id }}" | |
data-swatch-index="{{ forloop.index0 }}" | |
{% if visible %}aria-current="true"{%- endif -%} | |
{% if current_variant.featured_media %} | |
data-swatch-image="{{ current_variant.featured_media.preview_image.src }}" | |
{% endif %} | |
{% if current_variant.featured_media %} | |
data-swatch-image-id="{{ current_variant.featured_media.id }}" | |
{% endif %} | |
> | |
<span class="visually-hidden">{{ color_swatch_name }}</span> | |
</a> | |
</radio-swatch> | |
{% endcapture %} | |
{% endfor %} | |
{% else %} | |
{%- if inline_variant_buttons -%} | |
{%- assign inline_variants = product.variants -%} | |
{%- endif -%} | |
{%- liquid | |
assign selected_variant = product.selected_variant | default: product.variants[0] | |
if preload | |
assign preload_variant = true | |
endif | |
if eagerload | |
assign eagerload_variant = true | |
endif | |
-%} | |
{% render 'product-grid-item-variant', | |
product: product, | |
variant: selected_variant, | |
badge_string: badge_string, | |
visible: true, | |
instant_add_button: instant_add_button, | |
inline_variant_buttons: inline_variant_buttons, | |
inline_variants: inline_variants, | |
section_width: section_width, | |
preload: preload_variant, | |
eagerload: eagerload_variant, | |
placeholder: placeholder, | |
columns_desktop: columns_desktop, | |
columns_tablet: columns_tablet, | |
columns_mobile: columns_mobile | |
%} | |
{% endif %} | |
<div class="product__grid__info {{ text_align | default: settings.collection_text_alignment | default: 'text-center' }}"> | |
<a | |
href="{{ product.url }}" data-grid-link aria-label="{{ product.title | strip_html | escape }}" | |
{% comment %} The link wrapping the product variant image is already focusable, so this does not need to be {% endcomment %} | |
tabindex="-1" | |
> | |
<p class="visually-hidden">{{ product.title | strip_html | escape }}</p> | |
<div class="product__grid__title__wrapper"> | |
<p id="product-{{ product.id }}-title" class="product__grid__title"> | |
{{ product.title | strip_html | escape }} | |
</p> | |
{%- if settings.product_grid_show_rating and product.metafields.reviews.rating.value != blank -%} | |
<div class="rating__wrapper__grid"> | |
{% render 'product-rating', product: product, show_rating_count: settings.product_grid_show_rating_count %} | |
</div> | |
{%- endif -%} | |
</div> | |
<spark-product-card parent-id="{{ product.id }}"></spark-product-card> | |
<div data-spark="b2c-only" class="product__grid__price {% if settings.show_cutline %} product__grid__price--nowrap{% endif %}"> | |
{%- if settings.show_cutline -%} | |
<span class="product__grid__cutline">{{ product.metafields.theme.cutline.value }}</span> | |
{%- endif -%} | |
<span class="price{% if on_sale %} on-sale{% endif %}"> | |
{% if product.price_varies %}{{ 'products.general.from' | t }} {% endif %} | |
{%- if settings.currency_code_enable -%} | |
{{ product.price | money_with_currency }} | |
{%- else -%} | |
{{ product.price | money }} | |
{%- endif -%} | |
</span> | |
{% if on_sale %} | |
<span class="compare-at"> | |
{%- if settings.currency_code_enable -%} | |
{{ product.compare_at_price | money_with_currency }} | |
{%- else -%} | |
{{ product.compare_at_price | money }} | |
{%- endif -%} | |
</span> | |
{% endif %} | |
</div> | |
{% if product.selected_or_first_available_variant.unit_price %} | |
{% capture unit_price_separator %} | |
<span aria-hidden="true">/</span><span class="visually-hidden">{{ 'general.accessibility.unit_price_separator' | t }} </span> | |
{% endcapture %} | |
{% capture unit_price_base_unit %} | |
{% if product.selected_or_first_available_variant.unit_price_measurement.reference_value != 1 %} | |
{{ product.selected_or_first_available_variant.unit_price_measurement.reference_value }} | |
{% endif %} | |
{{ product.selected_or_first_available_variant.unit_price_measurement.reference_unit }} | |
{% endcapture %} | |
<p class="product__grid__price__unit"> | |
<span class="visually-hidden">{{ 'products.product.unit_price_label' | t }}</span> | |
<span class="price-per-unit"> | |
{%- if settings.currency_code_enable -%} | |
{{ product.selected_or_first_available_variant.unit_price | money_with_currency }} | |
{%- else -%} | |
{{ product.selected_or_first_available_variant.unit_price | money }} | |
{%- endif -%} | |
{{ unit_price_separator }}{{ unit_price_base_unit }} | |
</span> | |
</p> | |
{% endif %} | |
{% if sold_out %} | |
<p class="product__grid__price__sold"> | |
<em>{{ 'products.product.sold_out' | t }}</em> | |
</p> | |
{% endif %} | |
</a> | |
{%- if has_siblings -%} | |
{%- assign sibs_collection = collections[product.metafields.theme.siblings.value] -%} | |
{% if sibs_collection != blank %} | |
<div class="product__grid__sibs"> | |
<div class="grid__swatch__container"> | |
<p class="grid__swatch__placeholder">{{ 'collections.general.swatches_with_count' | t: count: sibs_collection.products_count }}</p> | |
<div data-spark="b2c-only" class="grid__swatch__hover"> | |
<div class="sibs__slider"> | |
<div class="sibs__inner" data-sibling-inner data-scrollbar data-scrollbar-slider> | |
{%- for sib_product in sibs_collection.products limit: 50 -%} | |
{%- assign title_safe = sib_product.title | strip_html | escape -%} | |
{%- assign color_name = sib_product.metafields.theme.cutline.value | default: title_safe -%} | |
<div class="siblings__link__holder {% if sib_product.available == false %} sold-out{% endif %}"> | |
<a | |
href="{{ sib_product.url }}" | |
class="siblings__link" | |
data-sibling-swatch-link | |
data-grid-item-variant="{{ sib_product.variants[0].id }}" | |
data-grid-item-swatch-image="0" | |
title="{{ color_name }}" | |
{% if sib_product.handle == product.handle %}aria-current="true"{%- endif -%} | |
> | |
<div class="siblings__swatch"> | |
<div class="sibling__image{% if settings.swatches_squares %} sibling__image--square{% endif %}"> | |
{% assign image = sib_product.featured_media.preview_image %} | |
{% assign image_width = 26 %} | |
{% assign image_width_2x = image_width | times: 2 | at_most: image.width %} | |
{% assign alt = image.alt | default: color_name %} | |
{% capture srcset %} | |
{{ image | image_url: width: image_width_2x }} 2x, | |
{{ image | image_url: width: image_width }} | |
{% endcapture %} | |
{%- render 'image', | |
img_object: image, | |
wh_ratio: 1.0, | |
srcset: srcset, | |
fetchpriority: 'low', | |
width: image_width, | |
placeholder: placeholder, | |
alt: alt | |
-%} | |
</div> | |
</div> | |
</a> | |
</div> | |
{%- endfor -%} | |
</div> | |
<button type="button" class="tabs__arrow tabs__arrow--prev is-hidden" data-scrollbar-arrow-prev> | |
<span class="visually-hidden">{{ 'general.accessibility.see_all' | t }}</span> | |
</button> | |
<button type="button" class="tabs__arrow tabs__arrow--next is-hidden" data-scrollbar-arrow-next> | |
<span class="visually-hidden">{{ 'general.accessibility.see_all' | t }}</span> | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
{% endif %} | |
{%- elsif has_swatches and swatch_link_markup != '' -%} | |
<div class="grid__swatch__container"> | |
<p class="grid__swatch__placeholder">{{ 'collections.general.swatches_with_count' | t: count: swatch_option.values.size }}</p> | |
<div class="grid__swatch__hover" aria-label="Options" data-swatch-handle="{{ product.handle }}" data-swatch-label="{{ label }}" data-sibling-inner data-scrollbar data-scrollbar-slider> | |
{{ swatch_link_markup }}{% if swatch_limit_plus > 0 %} <span>+{{ swatch_limit_plus }}</span>{% endif %} | |
</div> | |
<button type="button" class="tabs__arrow tabs__arrow--prev is-hidden" data-scrollbar-arrow-prev> | |
<span class="visually-hidden">{{ 'general.accessibility.see_all' | t }}</span> | |
</button> | |
<button type="button" class="tabs__arrow tabs__arrow--next is-hidden" data-scrollbar-arrow-next> | |
<span class="visually-hidden">{{ 'general.accessibility.see_all' | t }}</span> | |
</button> | |
</div> | |
{%- endif -%} | |
</div> | |
</product-grid-item> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment