Skip to content

Instantly share code, notes, and snippets.

@odessy
Created January 14, 2025 22:28
Show Gist options
  • Save odessy/69f5df30e7d2a55b8de00fe021f86c93 to your computer and use it in GitHub Desktop.
Save odessy/69f5df30e7d2a55b8de00fe021f86c93 to your computer and use it in GitHub Desktop.
Swatches limit pipeline
<!-- /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 }}&nbsp;</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