initial commit
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
{% comment %}
|
||||
Renders an article card for a given blog with settings to either show the image or not.
|
||||
|
||||
Accepts:
|
||||
- blog: {Object} Blog object
|
||||
- article: {Object} Article object
|
||||
- media_aspect_ratio: {String} The setting changes the aspect ratio of the article image, if shown
|
||||
- media_height: {String} The setting changes the height of the article image. Overrides media_aspect_ratio.
|
||||
- show_image: {String} The setting either show the article image or not. If it's not included it will show the image by default
|
||||
- show_date: {String} The setting either show the article date or not. If it's not included it will not show the image by default
|
||||
- show_author: {String} The setting either show the article author or not. If it's not included it will not show the author by default
|
||||
- show_badge: {String} The setting either show the blog badge or not.
|
||||
- lazy_load: {Boolean} Image should be lazy loaded. Default: true (optional)
|
||||
|
||||
Usage:
|
||||
{% render 'article-card' blog: blog, article: article, show_image: section.settings.show_image %}
|
||||
{% endcomment %}
|
||||
|
||||
{%- if article and article != empty -%}
|
||||
{%- liquid
|
||||
assign ratio = 1
|
||||
if media_aspect_ratio != null
|
||||
assign ratio = media_aspect_ratio
|
||||
endif
|
||||
-%}
|
||||
<div class="article-card-wrapper card-wrapper underline-links-hover">
|
||||
{% comment %} <article aria-labelledby="Article-{{ article.id }}"> {% endcomment %}
|
||||
<div
|
||||
class="
|
||||
card article-card
|
||||
card--{{ settings.blog_card_style }}
|
||||
{% if media_height and media_height != 'adapt' %} article-card__image--{{ media_height }}{% endif %}
|
||||
{% if article.image and show_image %} card--media{% else %} card--text{% endif %}
|
||||
{% if settings.blog_card_style == 'card' %} color-{{ settings.blog_card_color_scheme }} gradient{% endif %}
|
||||
{% if settings.blog_card_style == 'card' and media_height == nil and article.image == empty or show_image == false %} ratio{% endif %}
|
||||
"
|
||||
style="--ratio-percent: {{ 1 | divided_by: ratio | times: 100 }}%;"
|
||||
>
|
||||
<div
|
||||
class="card__inner {% if settings.blog_card_style == 'standard' %} color-{{ settings.blog_card_color_scheme }} gradient{% endif %}{% if article.image and show_image or settings.blog_card_style == 'standard' %} ratio{% endif %}"
|
||||
style="--ratio-percent: {{ 1 | divided_by: ratio | times: 100 }}%;"
|
||||
>
|
||||
{%- if show_image == true and article.image -%}
|
||||
<div class="article-card__image-wrapper card__media">
|
||||
<div
|
||||
class="article-card__image media media--hover-effect"
|
||||
{% if section.settings.media_height == 'adapt' %}
|
||||
style="padding-bottom: {{ 1 | divided_by: article.image.aspect_ratio | times: 100 }}%;"
|
||||
{% endif %}
|
||||
>
|
||||
{% comment %}theme-check-disable ImgLazyLoading{% endcomment %}
|
||||
<img
|
||||
srcset="
|
||||
{%- if article.image.src.width >= 165 -%}{{ article.image.src | image_url: width: 165 }} 165w,{%- endif -%}
|
||||
{%- if article.image.src.width >= 360 -%}{{ article.image.src | image_url: width: 360 }} 360w,{%- endif -%}
|
||||
{%- if article.image.src.width >= 533 -%}{{ article.image.src | image_url: width: 533 }} 533w,{%- endif -%}
|
||||
{%- if article.image.src.width >= 720 -%}{{ article.image.src | image_url: width: 720 }} 720w,{%- endif -%}
|
||||
{%- if article.image.src.width >= 1000 -%}{{ article.image.src | image_url: width: 1000 }} 1000w,{%- endif -%}
|
||||
{%- if article.image.src.width >= 1500 -%}{{ article.image.src | image_url: width: 1500 }} 1500w,{%- endif -%}
|
||||
{{ article.image.src | image_url }} {{ article.image.src.width }}w
|
||||
"
|
||||
src="{{ article.image.src | image_url: width: 533 }}"
|
||||
sizes="(min-width: {{ settings.page_width }}px) {{ settings.page_width | minus: 100 | divided_by: 2 }}px, (min-width: 750px) calc((100vw - 130px) / 2), calc((100vw - 50px) / 2)"
|
||||
alt="{{ article.image.src.alt | escape }}"
|
||||
class="motion-reduce"
|
||||
{% unless lazy_load == false %}
|
||||
loading="lazy"
|
||||
{% endunless %}
|
||||
width="{{ article.image.width }}"
|
||||
height="{{ article.image.height }}"
|
||||
>
|
||||
{% comment %}theme-check-enable ImgLazyLoading{% endcomment %}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<div class="card__content">
|
||||
<div class="card__information">
|
||||
<h3 class="card__heading{% if show_excerpt %} h2{% endif %}">
|
||||
<a href="{{ article.url }}" class="full-unstyled-link">
|
||||
{{ article.title | truncate: 50 | escape }}
|
||||
</a>
|
||||
</h3>
|
||||
<div class="article-card__info caption-with-letter-spacing h5">
|
||||
{%- if show_date -%}
|
||||
<span class="circle-divider">{{ article.published_at | time_tag: format: 'date' }}</span>
|
||||
{%- endif -%}
|
||||
{%- if show_author -%}
|
||||
<span>{{ article.author }}</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- if show_excerpt -%}
|
||||
{%- if article.excerpt.size > 0 or article.content.size > 0 -%}
|
||||
<p class="article-card__excerpt rte-width">
|
||||
{%- if article.excerpt.size > 0 -%}
|
||||
{{ article.excerpt | strip_html | truncatewords: 30 }}
|
||||
{%- else -%}
|
||||
{{ article.content | strip_html | truncatewords: 30 }}
|
||||
{%- endif -%}
|
||||
</p>
|
||||
{%- endif -%}
|
||||
<div class="article-card__footer">
|
||||
{%- if article.comments_count > 0 and blog.comments_enabled? -%}
|
||||
<span>{{ 'blogs.article.comments' | t: count: article.comments_count }}</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- if show_badge -%}
|
||||
<div class="card__badge {{ settings.badge_position }}">
|
||||
<span class="badge color-{{ settings.color_schemes | first }}">{{ 'blogs.article.blog' | t }}</span>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card__content">
|
||||
<div class="card__information">
|
||||
<h3 class="card__heading{% if show_excerpt %} h2{% endif %}">
|
||||
<a href="{{ article.url }}" class="full-unstyled-link">
|
||||
{{ article.title | truncate: 50 | escape }}
|
||||
</a>
|
||||
</h3>
|
||||
<div class="article-card__info caption-with-letter-spacing h5">
|
||||
{%- if show_date -%}
|
||||
<span class="circle-divider">{{ article.published_at | time_tag: format: 'date' }}</span>
|
||||
{%- endif -%}
|
||||
{%- if show_author -%}
|
||||
<span>{{ article.author }}</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- if show_excerpt -%}
|
||||
{%- if article.excerpt.size > 0 or article.content.size > 0 -%}
|
||||
<p class="article-card__excerpt rte-width">
|
||||
{%- if article.excerpt.size > 0 -%}
|
||||
{{ article.excerpt | strip_html | truncatewords: 30 }}
|
||||
{%- else -%}
|
||||
{{ article.content | strip_html | truncatewords: 30 }}
|
||||
{%- endif -%}
|
||||
</p>
|
||||
{%- endif -%}
|
||||
<div class="article-card__footer">
|
||||
{%- if article.comments_count > 0 and blog.comments_enabled? -%}
|
||||
<span>{{ 'blogs.article.comments' | t: count: article.comments_count }}</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- if show_badge -%}
|
||||
<div class="card__badge {{ settings.badge_position }}">
|
||||
<span class="badge color-{{ settings.color_schemes | first }}">{{ 'blogs.article.blog' | t }}</span>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
@@ -0,0 +1,151 @@
|
||||
{% comment %}
|
||||
Renders product buy-buttons.
|
||||
Accepts:
|
||||
- product: {Object} product object.
|
||||
- block: {Object} passing the block information.
|
||||
- product_form_id: {String} product form id.
|
||||
- section_id: {String} id of section to which this snippet belongs.
|
||||
- show_pickup_availability: {Boolean} for the pickup availability. If true the pickup availability is rendered, false - not rendered (optional).
|
||||
|
||||
Usage:
|
||||
{% render 'buy-buttons', block: block, product: product, product_form_id: product_form_id, section_id: section.id, show_pickup_availability: true %}
|
||||
{% endcomment %}
|
||||
<div {{ block.shopify_attributes }}>
|
||||
{%- if product != blank -%}
|
||||
{%- liquid
|
||||
assign gift_card_recipient_feature_active = false
|
||||
if block.settings.show_gift_card_recipient and product.gift_card?
|
||||
assign gift_card_recipient_feature_active = true
|
||||
endif
|
||||
|
||||
assign show_dynamic_checkout = false
|
||||
if block.settings.show_dynamic_checkout and gift_card_recipient_feature_active == false
|
||||
assign show_dynamic_checkout = true
|
||||
endif
|
||||
-%}
|
||||
|
||||
<product-form
|
||||
class="product-form"
|
||||
data-hide-errors="{{ gift_card_recipient_feature_active }}"
|
||||
data-section-id="{{ section.id }}"
|
||||
>
|
||||
<div class="product-form__error-message-wrapper" role="alert" hidden>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-error.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="product-form__error-message"></span>
|
||||
</div>
|
||||
|
||||
{%- form 'product',
|
||||
product,
|
||||
id: product_form_id,
|
||||
class: 'form',
|
||||
novalidate: 'novalidate',
|
||||
data-type: 'add-to-cart-form'
|
||||
-%}
|
||||
<input
|
||||
type="hidden"
|
||||
name="id"
|
||||
value="{{ product.selected_or_first_available_variant.id }}"
|
||||
{% if product.selected_or_first_available_variant.available == false
|
||||
or quantity_rule_soldout
|
||||
or product.selected_or_first_available_variant == null
|
||||
%}
|
||||
disabled
|
||||
{% endif %}
|
||||
class="product-variant-id"
|
||||
>
|
||||
|
||||
{%- if gift_card_recipient_feature_active -%}
|
||||
{%- render 'gift-card-recipient-form', product: product, form: form, section: section -%}
|
||||
{%- endif -%}
|
||||
|
||||
<div class="product-form__buttons">
|
||||
{%- liquid
|
||||
assign check_against_inventory = true
|
||||
if product.selected_or_first_available_variant.inventory_management != 'shopify' or product.selected_or_first_available_variant.inventory_policy == 'continue'
|
||||
assign check_against_inventory = false
|
||||
endif
|
||||
if product.selected_or_first_available_variant.quantity_rule.min > product.selected_or_first_available_variant.inventory_quantity and check_against_inventory
|
||||
assign quantity_rule_soldout = true
|
||||
endif
|
||||
-%}
|
||||
<button
|
||||
id="ProductSubmitButton-{{ section_id }}"
|
||||
type="submit"
|
||||
name="add"
|
||||
class="product-form__submit button button--full-width {% if show_dynamic_checkout %}button--secondary{% else %}button--primary{% endif %}"
|
||||
{% if product.selected_or_first_available_variant.available == false
|
||||
or quantity_rule_soldout
|
||||
or product.selected_or_first_available_variant == null
|
||||
%}
|
||||
disabled
|
||||
{% endif %}
|
||||
>
|
||||
<span>
|
||||
{%- if product.selected_or_first_available_variant == null -%}
|
||||
{{ 'products.product.unavailable' | t }}
|
||||
{%- elsif product.selected_or_first_available_variant.available == false or quantity_rule_soldout -%}
|
||||
{{ 'products.product.sold_out' | t }}
|
||||
{%- else -%}
|
||||
{{ 'products.product.add_to_cart' | t }}
|
||||
{%- endif -%}
|
||||
</span>
|
||||
{%- render 'loading-spinner' -%}
|
||||
</button>
|
||||
{%- if show_dynamic_checkout -%}
|
||||
{{ form | payment_button }}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endform -%}
|
||||
</product-form>
|
||||
{%- else -%}
|
||||
<div class="product-form">
|
||||
<div class="product-form__buttons form">
|
||||
<button
|
||||
type="submit"
|
||||
name="add"
|
||||
class="product-form__submit button button--full-width button--primary"
|
||||
disabled
|
||||
>
|
||||
{{ 'products.product.sold_out' | t }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if show_pickup_availability -%}
|
||||
{{ 'component-pickup-availability.css' | asset_url | stylesheet_tag }}
|
||||
|
||||
{%- assign pick_up_availabilities = product.selected_or_first_available_variant.store_availabilities
|
||||
| where: 'pick_up_enabled', true
|
||||
-%}
|
||||
|
||||
<pickup-availability
|
||||
class="product__pickup-availabilities quick-add-hidden"
|
||||
{% if product.selected_or_first_available_variant.available and pick_up_availabilities.size > 0 %}
|
||||
available
|
||||
{% endif %}
|
||||
data-root-url="{{ routes.root_url }}"
|
||||
data-variant-id="{{ product.selected_or_first_available_variant.id }}"
|
||||
data-has-only-default-variant="{{ product.has_only_default_variant }}"
|
||||
data-product-page-color-scheme="gradient color-{{ section.settings.color_scheme }}"
|
||||
>
|
||||
<template>
|
||||
<pickup-availability-preview class="pickup-availability-preview">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-unavailable.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<div class="pickup-availability-info">
|
||||
<p class="caption-large">{{ 'products.product.pickup_availability.unavailable' | t }}</p>
|
||||
<button class="pickup-availability-button link link--text underlined-link">
|
||||
{{ 'products.product.pickup_availability.refresh' | t }}
|
||||
</button>
|
||||
</div>
|
||||
</pickup-availability-preview>
|
||||
</template>
|
||||
</pickup-availability>
|
||||
|
||||
<script src="{{ 'pickup-availability.js' | asset_url }}" defer="defer"></script>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
@@ -0,0 +1,169 @@
|
||||
{% comment %}
|
||||
Renders a collection card
|
||||
|
||||
Accepts:
|
||||
- card_collection: {Object} Collection Liquid object
|
||||
- media_aspect_ratio: {String} Size of the product image card. Values are "square" and "portrait". Default is "square" (optional)
|
||||
- columns: {Number}
|
||||
- extend_height: {Boolean} Card height extends to available container space. Default: false (optional)
|
||||
- wrapper_class: {String} Wrapper class for card (optional)
|
||||
- placeholder_image: {String} Placeholder image when collection is empty (optional)
|
||||
|
||||
Usage:
|
||||
{% render 'card-collection' %}
|
||||
{% endcomment %}
|
||||
|
||||
{%- liquid
|
||||
assign ratio = 1
|
||||
if card_collection.featured_image and media_aspect_ratio == 'portrait'
|
||||
assign ratio = 0.8
|
||||
elsif card_collection.featured_image and media_aspect_ratio == 'adapt'
|
||||
assign ratio = card_collection.featured_image.aspect_ratio
|
||||
endif
|
||||
if ratio == 0 or ratio == null
|
||||
assign ratio = 1
|
||||
endif
|
||||
assign card_color_scheme = settings.card_color_scheme
|
||||
assign card_style = settings.card_style
|
||||
if wrapper_class == null or wrapper_class == 'none'
|
||||
assign card_color_scheme = settings.collection_card_color_scheme
|
||||
assign card_style = settings.collection_card_style
|
||||
endif
|
||||
-%}
|
||||
|
||||
<div class="card-wrapper animate-arrow {% if wrapper_class and wrapper_class != 'none' %}{{ wrapper_class }}{% else %}collection-card-wrapper{% endif %}">
|
||||
<div
|
||||
class="
|
||||
card
|
||||
card--{{ card_style }}
|
||||
{% if card_collection.featured_image %} card--media{% else %} card--text{% endif %}
|
||||
{% if card_style == 'card' %} color-{{ card_color_scheme }} gradient{% endif %}
|
||||
{% if extend_height %} card--extend-height{% endif %}
|
||||
{% if card_collection.featured_image == nil and card_style == 'card' %} ratio{% endif %}
|
||||
"
|
||||
style="--ratio-percent: {{ 1 | divided_by: ratio | times: 100 }}%;"
|
||||
>
|
||||
<div
|
||||
class="card__inner {% if card_style == 'standard' %}color-{{ card_color_scheme }} gradient{% endif %}{% if card_collection.featured_image or card_style == 'standard' %} ratio{% endif %}"
|
||||
style="--ratio-percent: {{ 1 | divided_by: ratio | times: 100 }}%;"
|
||||
>
|
||||
{%- if card_collection.featured_image -%}
|
||||
<div class="card__media">
|
||||
<div class="media media--transparent media--hover-effect">
|
||||
<img
|
||||
srcset="
|
||||
{%- if card_collection.featured_image.width >= 165 -%}{{ card_collection.featured_image | image_url: width: 165 }} 165w,{%- endif -%}
|
||||
{%- if card_collection.featured_image.width >= 330 -%}{{ card_collection.featured_image | image_url: width: 330 }} 330w,{%- endif -%}
|
||||
{%- if card_collection.featured_image.width >= 535 -%}{{ card_collection.featured_image | image_url: width: 535 }} 535w,{%- endif -%}
|
||||
{%- if card_collection.featured_image.width >= 750 -%}{{ card_collection.featured_image | image_url: width: 750 }} 750w,{%- endif -%}
|
||||
{%- if card_collection.featured_image.width >= 1000 -%}{{ card_collection.featured_image | image_url: width: 1000 }} 1000w,{%- endif -%}
|
||||
{%- if card_collection.featured_image.width >= 1500 -%}{{ card_collection.featured_image | image_url: width: 1500 }} 1500w,{%- endif -%}
|
||||
{%- if card_collection.featured_image.width >= 3000 -%}{{ card_collection.featured_image | image_url: width: 3000 }} 3000w,{%- endif -%}
|
||||
{{ card_collection.featured_image | image_url }} {{ card_collection.featured_image.width }}w
|
||||
"
|
||||
src="{{ card_collection.featured_image | image_url: width: 1500 }}"
|
||||
sizes="
|
||||
(min-width: {{ settings.page_width }}px) {{ settings.page_width | minus: 100 | divided_by: columns }}px,
|
||||
(min-width: 750px) {% if columns > 1 %}calc((100vw - 10rem) / 2){% else %}calc(100vw - 10rem){% endif %},
|
||||
calc(100vw - 3rem)
|
||||
"
|
||||
alt="{{ card_collection.featured_image.alt | escape }}"
|
||||
height="{{ card_collection.featured_image.height }}"
|
||||
width="{{ card_collection.featured_image.width }}"
|
||||
loading="lazy"
|
||||
class="motion-reduce"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if card_collection == blank -%}
|
||||
<div class="card__media">
|
||||
{{ placeholder_image | placeholder_svg_tag: 'placeholder-svg' }}
|
||||
</div>
|
||||
{%- else -%}
|
||||
<div class="card__content">
|
||||
<div class="card__information">
|
||||
<h3 class="card__heading">
|
||||
<a
|
||||
{% if card_collection == blank %}
|
||||
role="link" aria-disabled="true"
|
||||
{% else %}
|
||||
href="{{ card_collection.url }}"
|
||||
{% endif %}
|
||||
class="full-unstyled-link"
|
||||
>
|
||||
{%- if card_collection.title != blank -%}
|
||||
{{- card_collection.title | escape -}}
|
||||
{%- else -%}
|
||||
{{ 'onboarding.collection_title' | t }}
|
||||
{%- endif -%}
|
||||
{%- if card_collection.description == blank -%}
|
||||
<span class="icon-wrap">
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{%- endif %}
|
||||
</a>
|
||||
</h3>
|
||||
{%- if card_collection.description != blank -%}
|
||||
<p class="card__caption">
|
||||
{{- card_collection.description | strip_html | truncatewords: 12 -}}
|
||||
<span class="icon-wrap">
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</p>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- if card_collection != blank and card_style == 'card' or card_collection.featured_image -%}
|
||||
<div class="card__content">
|
||||
<div class="card__information">
|
||||
<h3 class="card__heading">
|
||||
<a
|
||||
{% if card_collection == blank %}
|
||||
role="link" aria-disabled="true"
|
||||
{% else %}
|
||||
href="{{ card_collection.url }}"
|
||||
{% endif %}
|
||||
class="full-unstyled-link"
|
||||
>
|
||||
{%- if card_collection.title != blank -%}
|
||||
{{- card_collection.title | escape -}}
|
||||
{%- else -%}
|
||||
{{ 'onboarding.collection_title' | t }}
|
||||
{%- endif -%}
|
||||
{%- if card_collection.featured_image or card_collection.description == blank -%}
|
||||
<span class="icon-wrap">
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{%- endif %}
|
||||
</a>
|
||||
</h3>
|
||||
{%- if card_collection.featured_image == null and card_collection.description != blank -%}
|
||||
<p class="card__caption">
|
||||
{{- card_collection.description | strip_html | truncatewords: 12 -}}
|
||||
<span class="icon-wrap">
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</p>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if card_collection == blank -%}
|
||||
<div class="card__content">
|
||||
<div class="card__information">
|
||||
<h3 class="card__heading card__heading--placeholder">
|
||||
<a role="link" aria-disabled="true" class="full-unstyled-link">
|
||||
{{ 'onboarding.collection_title' | t }}
|
||||
<span class="icon-wrap">
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,627 @@
|
||||
{% comment %}
|
||||
Renders a product card
|
||||
|
||||
Accepts:
|
||||
- card_product: {Object} Product Liquid object (optional)
|
||||
- media_aspect_ratio: {String} Size of the product image card. Values are "square" and "portrait". Default is "square" (optional)
|
||||
- image_shape: {String} Image mask to apply to the product image card. Values are "arch", "blob", "chevronleft", "chevronright", "diamond", "parallelogram", and "round". (optional)
|
||||
- show_secondary_image: {Boolean} Show the secondary image on hover. Default: false (optional)
|
||||
- show_vendor: {Boolean} Show the product vendor. Default: false
|
||||
- show_rating: {Boolean} Show the product rating. Default: false
|
||||
- extend_height: {Boolean} Card height extends to available container space. Default: true (optional)
|
||||
- lazy_load: {Boolean} Image should be lazy loaded. Default: true (optional)
|
||||
- skip_styles: {Boolean} Don't include component styles. Useful when rendering multiple product cards in a loop. Default: false (optional)
|
||||
- quick_add: {Boolean} Show the quick add button.
|
||||
- section_id: {String} The ID of the section that contains this card.
|
||||
- horizontal_class: {Boolean} Add a card--horizontal class if set to true. Default: false (optional)
|
||||
- horizontal_quick_add: {Boolean} Changes the quick add button styles when set to true. Default: false (optional)
|
||||
- placeholder_image: {String} The placeholder image to use when no product exists. Default: 'product-apparel-2' (optional)
|
||||
|
||||
Usage:
|
||||
{% render 'card-product', show_vendor: section.settings.show_vendor %}
|
||||
{% endcomment %}
|
||||
{%- unless skip_styles -%}
|
||||
{{ 'component-rating.css' | asset_url | stylesheet_tag }}
|
||||
{{ 'component-volume-pricing.css' | asset_url | stylesheet_tag }}
|
||||
|
||||
{{ 'component-price.css' | asset_url | stylesheet_tag }}
|
||||
{{ 'quick-order-list.css' | asset_url | stylesheet_tag }}
|
||||
{{ 'quantity-popover.css' | asset_url | stylesheet_tag }}
|
||||
{%- endunless -%}
|
||||
{%- if card_product and card_product != empty -%}
|
||||
{%- liquid
|
||||
assign ratio = 1
|
||||
if card_product.featured_media and media_aspect_ratio == 'portrait'
|
||||
assign ratio = 0.8
|
||||
elsif card_product.featured_media and media_aspect_ratio == 'adapt'
|
||||
assign ratio = card_product.featured_media.aspect_ratio
|
||||
endif
|
||||
if ratio == 0 or ratio == null
|
||||
assign ratio = 1
|
||||
endif
|
||||
-%}
|
||||
|
||||
<product-component view-event-payload="{{ card_product | standard_event_data: 'view', context: product_view_context | escape }}">
|
||||
<div class="card-wrapper product-card-wrapper underline-links-hover">
|
||||
<div
|
||||
class="
|
||||
card card--{{ settings.card_style }}
|
||||
{% if card_product.featured_media %} card--media{% else %} card--text{% endif %}
|
||||
{% if settings.card_style == 'card' %} color-{{ settings.card_color_scheme }} gradient{% endif %}
|
||||
{% if image_shape and image_shape != 'default' %} card--shape{% endif %}
|
||||
{% if extend_height %} card--extend-height{% endif %}
|
||||
{% if card_product.featured_media == nil and settings.card_style == 'card' %} ratio{% endif %}
|
||||
{% if horizontal_class %} card--horizontal{% endif %}
|
||||
"
|
||||
style="--ratio-percent: {{ 1 | divided_by: ratio | times: 100 }}%;"
|
||||
>
|
||||
<div
|
||||
class="card__inner {% if settings.card_style == 'standard' %}color-{{ settings.card_color_scheme }} gradient{% endif %}{% if card_product.featured_media or settings.card_style == 'standard' %} ratio{% endif %}"
|
||||
style="--ratio-percent: {{ 1 | divided_by: ratio | times: 100 }}%;"
|
||||
>
|
||||
{%- if card_product.featured_media -%}
|
||||
<div class="card__media{% if image_shape and image_shape != 'default' %} shape--{{ image_shape }} color-{{ settings.card_color_scheme }} gradient{% endif %}">
|
||||
<div class="media media--transparent media--hover-effect">
|
||||
{% comment %}theme-check-disable ImgLazyLoading{% endcomment %}
|
||||
<img
|
||||
srcset="
|
||||
{%- if card_product.featured_media.width >= 165 -%}{{ card_product.featured_media | image_url: width: 165 }} 165w,{%- endif -%}
|
||||
{%- if card_product.featured_media.width >= 360 -%}{{ card_product.featured_media | image_url: width: 360 }} 360w,{%- endif -%}
|
||||
{%- if card_product.featured_media.width >= 533 -%}{{ card_product.featured_media | image_url: width: 533 }} 533w,{%- endif -%}
|
||||
{%- if card_product.featured_media.width >= 720 -%}{{ card_product.featured_media | image_url: width: 720 }} 720w,{%- endif -%}
|
||||
{%- if card_product.featured_media.width >= 940 -%}{{ card_product.featured_media | image_url: width: 940 }} 940w,{%- endif -%}
|
||||
{%- if card_product.featured_media.width >= 1066 -%}{{ card_product.featured_media | image_url: width: 1066 }} 1066w,{%- endif -%}
|
||||
{{ card_product.featured_media | image_url }} {{ card_product.featured_media.width }}w
|
||||
"
|
||||
src="{{ card_product.featured_media | image_url: width: 533 }}"
|
||||
sizes="(min-width: {{ settings.page_width }}px) {{ settings.page_width | minus: 130 | divided_by: 4 }}px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)"
|
||||
alt="{{ card_product.featured_media.alt | escape }}"
|
||||
class="motion-reduce"
|
||||
{% unless lazy_load == false %}
|
||||
loading="lazy"
|
||||
{% endunless %}
|
||||
width="{{ card_product.featured_media.width }}"
|
||||
height="{{ card_product.featured_media.height }}"
|
||||
>
|
||||
{% comment %}theme-check-enable ImgLazyLoading{% endcomment %}
|
||||
|
||||
{%- if card_product.media[1] != null and show_secondary_image -%}
|
||||
<img
|
||||
srcset="
|
||||
{%- if card_product.media[1].width >= 165 -%}{{ card_product.media[1] | image_url: width: 165 }} 165w,{%- endif -%}
|
||||
{%- if card_product.media[1].width >= 360 -%}{{ card_product.media[1] | image_url: width: 360 }} 360w,{%- endif -%}
|
||||
{%- if card_product.media[1].width >= 533 -%}{{ card_product.media[1] | image_url: width: 533 }} 533w,{%- endif -%}
|
||||
{%- if card_product.media[1].width >= 720 -%}{{ card_product.media[1] | image_url: width: 720 }} 720w,{%- endif -%}
|
||||
{%- if card_product.media[1].width >= 940 -%}{{ card_product.media[1] | image_url: width: 940 }} 940w,{%- endif -%}
|
||||
{%- if card_product.media[1].width >= 1066 -%}{{ card_product.media[1] | image_url: width: 1066 }} 1066w,{%- endif -%}
|
||||
{{ card_product.media[1] | image_url }} {{ card_product.media[1].width }}w
|
||||
"
|
||||
src="{{ card_product.media[1] | image_url: width: 533 }}"
|
||||
sizes="(min-width: {{ settings.page_width }}px) {{ settings.page_width | minus: 130 | divided_by: 4 }}px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)"
|
||||
alt="{{ card_product.media[1].alt | escape }}"
|
||||
class="motion-reduce"
|
||||
loading="lazy"
|
||||
width="{{ card_product.media[1].width }}"
|
||||
height="{{ card_product.media[1].height }}"
|
||||
>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<div class="card__content">
|
||||
<div class="card__information">
|
||||
<h3
|
||||
class="card__heading"
|
||||
{% if card_product.featured_media == null and settings.card_style == 'standard' %}
|
||||
id="title-{{ section_id }}-{{ card_product.id }}"
|
||||
{% endif %}
|
||||
>
|
||||
<a
|
||||
href="{{ card_product.url }}"
|
||||
id="StandardCardNoMediaLink-{{ section_id }}-{{ card_product.id }}"
|
||||
class="full-unstyled-link"
|
||||
aria-labelledby="StandardCardNoMediaLink-{{ section_id }}-{{ card_product.id }}{% if card_product.available == false or card_product.compare_at_price > card_product.price %} NoMediaStandardBadge-{{ section_id }}-{{ card_product.id }}{% endif %}"
|
||||
>
|
||||
{{ card_product.title | escape }}
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card__badge {{ settings.badge_position }}">
|
||||
{%- if card_product.available == false -%}
|
||||
<span
|
||||
id="NoMediaStandardBadge-{{ section_id }}-{{ card_product.id }}"
|
||||
class="badge badge--bottom-left color-{{ settings.sold_out_badge_color_scheme }}"
|
||||
>
|
||||
{{- 'products.product.sold_out' | t -}}
|
||||
</span>
|
||||
{%- elsif card_product.compare_at_price > card_product.price and card_product.available -%}
|
||||
<span
|
||||
id="NoMediaStandardBadge-{{ section_id }}-{{ card_product.id }}"
|
||||
class="badge badge--bottom-left color-{{ settings.sale_badge_color_scheme }}"
|
||||
>
|
||||
{{- 'products.product.on_sale' | t -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card__content">
|
||||
<div class="card__information">
|
||||
<h3
|
||||
class="card__heading{% if card_product.featured_media or settings.card_style == 'standard' %} h5{% endif %}"
|
||||
{% if card_product.featured_media or settings.card_style == 'card' %}
|
||||
id="title-{{ section_id }}-{{ card_product.id }}"
|
||||
{% endif %}
|
||||
>
|
||||
<a
|
||||
href="{{ card_product.url }}"
|
||||
id="CardLink-{{ section_id }}-{{ card_product.id }}"
|
||||
class="full-unstyled-link"
|
||||
aria-labelledby="CardLink-{{ section_id }}-{{ card_product.id }}{% if card_product.available == false or card_product.compare_at_price > card_product.price %} Badge-{{ section_id }}-{{ card_product.id }}{% endif %}"
|
||||
>
|
||||
{{ card_product.title | escape }}
|
||||
</a>
|
||||
</h3>
|
||||
<div class="card-information">
|
||||
{%- if show_vendor -%}
|
||||
<span class="visually-hidden">{{ 'accessibility.vendor' | t }}</span>
|
||||
<div class="caption-with-letter-spacing light">{{ card_product.vendor }}</div>
|
||||
{%- endif -%}
|
||||
|
||||
<span class="caption-large light">{{ block.settings.description | escape }}</span>
|
||||
|
||||
{%- if show_rating and card_product.metafields.reviews.rating.value != blank -%}
|
||||
{% liquid
|
||||
assign rating_decimal = 0
|
||||
assign decimal = card_product.metafields.reviews.rating.value.rating | modulo: 1
|
||||
if decimal >= 0.3 and decimal <= 0.7
|
||||
assign rating_decimal = 0.5
|
||||
elsif decimal > 0.7
|
||||
assign rating_decimal = 1
|
||||
endif
|
||||
%}
|
||||
<div
|
||||
class="rating"
|
||||
role="img"
|
||||
aria-label="{{ 'accessibility.star_reviews_info' | t: rating_value: card_product.metafields.reviews.rating.value, rating_max: card_product.metafields.reviews.rating.value.scale_max }}"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="rating-star"
|
||||
style="--rating: {{ card_product.metafields.reviews.rating.value.rating | floor }}; --rating-max: {{ card_product.metafields.reviews.rating.value.scale_max }}; --rating-decimal: {{ rating_decimal }};"
|
||||
></span>
|
||||
</div>
|
||||
<p class="rating-text caption">
|
||||
<span aria-hidden="true">
|
||||
{{- card_product.metafields.reviews.rating.value }} /
|
||||
{{ card_product.metafields.reviews.rating.value.scale_max -}}
|
||||
</span>
|
||||
</p>
|
||||
<p class="rating-count caption">
|
||||
<span aria-hidden="true">({{ card_product.metafields.reviews.rating_count }})</span>
|
||||
<span class="visually-hidden">
|
||||
{{- card_product.metafields.reviews.rating_count }}
|
||||
{{ 'accessibility.total_reviews' | t -}}
|
||||
</span>
|
||||
</p>
|
||||
{%- endif -%}
|
||||
|
||||
{% render 'price', product: card_product, price_class: '', show_compare_at_price: true %}
|
||||
{%- if card_product.quantity_price_breaks_configured? -%}
|
||||
{% if card_product.variants_count == 1 and quick_add == 'bulk' %}
|
||||
{% liquid
|
||||
assign quantity_rule = card_product.selected_or_first_available_variant.quantity_rule
|
||||
assign has_qty_rules = false
|
||||
if quantity_rule.increment > 1 or quantity_rule.min > 1 or quantity_rule.max != null
|
||||
assign has_qty_rules = true
|
||||
endif
|
||||
%}
|
||||
<quantity-popover>
|
||||
<button class="card__information-volume-pricing-note card__information-volume-pricing-note--button card__information-volume-pricing-note--button-{{ settings.card_text_alignment }} quantity-popover__info-button--icon-only button button button--tertiary medium-hide small-hide">
|
||||
<span class="caption">{{ 'products.product.volume_pricing.note' | t }}</span>
|
||||
</button>
|
||||
<button class="card__information-volume-pricing-note card__information-volume-pricing-note--button card__information-volume-pricing-note--button-{{ settings.card_text_alignment }} quantity-popover__info-button--icon-with-label button button--tertiary large-up-hide">
|
||||
<span class="caption">{{ 'products.product.volume_pricing.note' | t }}</span>
|
||||
</button>
|
||||
{% else %}
|
||||
<div class="card__information-volume-pricing-note">
|
||||
<span class="caption">{{ 'products.product.volume_pricing.note' | t }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if card_product.variants_count == 1 and quick_add == 'bulk' %}
|
||||
<div
|
||||
class="global-settings-popup quantity-popover__info"
|
||||
tabindex="-1"
|
||||
hidden
|
||||
id="quantity-popover-info-{{ card_product.selected_or_first_available_variant.id }}"
|
||||
>
|
||||
{%- if has_qty_rules -%}
|
||||
<div class="quantity__rules caption no-js-hidden">
|
||||
{%- if quantity_rule.increment > 1 -%}
|
||||
<span class="divider">
|
||||
{{- 'products.product.quantity.multiples_of' | t: quantity: quantity_rule.increment -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- if quantity_rule.min > 1 -%}
|
||||
<span class="divider">
|
||||
{{- 'products.product.quantity.min_of' | t: quantity: quantity_rule.min -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- if quantity_rule.max != null -%}
|
||||
<span class="divider">
|
||||
{{- 'products.product.quantity.max_of' | t: quantity: quantity_rule.max -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<button
|
||||
class="button-close button button--tertiary large-up-hide"
|
||||
type="button"
|
||||
aria-label="{{ 'accessibility.close' | t }}"
|
||||
>
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</button>
|
||||
{%- if card_product.selected_or_first_available_variant.quantity_price_breaks.size > 0 -%}
|
||||
<volume-pricing class="parent-display">
|
||||
<ul class="list-unstyled">
|
||||
<li>
|
||||
<span>{{ card_product.selected_or_first_available_variant.quantity_rule.min }}+</span>
|
||||
{%- assign price = card_product.selected_or_first_available_variant.price
|
||||
| money_with_currency
|
||||
-%}
|
||||
<span>{{ 'sections.quick_order_list.each' | t: money: price }}</span>
|
||||
</li>
|
||||
{%- for price_break in card_product.selected_or_first_available_variant.quantity_price_breaks -%}
|
||||
<li>
|
||||
<span>
|
||||
{{- price_break.minimum_quantity -}}
|
||||
<span aria-hidden="true">+</span></span
|
||||
>
|
||||
{%- assign price = price_break.price | money_with_currency -%}
|
||||
<span> {{ 'sections.quick_order_list.each' | t: money: price }}</span>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</volume-pricing>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</quantity-popover>
|
||||
{% endif %}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div>
|
||||
{% assign product_form_id = 'quick-add-' | append: section_id | append: card_product.id %}
|
||||
{% if quick_add == 'standard' %}
|
||||
<div class="quick-add no-js-hidden">
|
||||
{%- liquid
|
||||
assign qty_rules = false
|
||||
if card_product.selected_or_first_available_variant.quantity_rule.min > 1 or card_product.selected_or_first_available_variant.quantity_rule.max != null or card_product.selected_or_first_available_variant.quantity_rule.increment > 1
|
||||
assign qty_rules = true
|
||||
endif
|
||||
-%}
|
||||
{%- if card_product.variants_count > 1 or qty_rules -%}
|
||||
<modal-opener data-modal="#QuickAdd-{{ card_product.id }}">
|
||||
<button
|
||||
id="{{ product_form_id }}-submit"
|
||||
type="submit"
|
||||
name="add"
|
||||
class="quick-add__submit button button--full-width button--secondary{% if horizontal_quick_add %} card--horizontal__quick-add animate-arrow{% endif %}"
|
||||
aria-haspopup="dialog"
|
||||
aria-labelledby="{{ product_form_id }}-submit title-{{ section_id }}-{{ card_product.id }}"
|
||||
data-product-url="{{ card_product.url }}"
|
||||
>
|
||||
{{ 'products.product.choose_options' | t }}
|
||||
{%- if horizontal_quick_add -%}
|
||||
<span class="icon-wrap">
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- render 'loading-spinner' -%}
|
||||
</button>
|
||||
</modal-opener>
|
||||
<quick-add-modal id="QuickAdd-{{ card_product.id }}" class="quick-add-modal">
|
||||
<div
|
||||
role="dialog"
|
||||
aria-label="{{ 'products.product.choose_product_options' | t: product_name: card_product.title | escape }}"
|
||||
aria-modal="true"
|
||||
class="quick-add-modal__content global-settings-popup"
|
||||
tabindex="-1"
|
||||
>
|
||||
<button
|
||||
id="ModalClose-{{ card_product.id }}"
|
||||
type="button"
|
||||
class="quick-add-modal__toggle"
|
||||
aria-label="{{ 'accessibility.close' | t }}"
|
||||
>
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</button>
|
||||
<div id="QuickAddInfo-{{ card_product.id }}" class="quick-add-modal__content-info"></div>
|
||||
</div>
|
||||
</quick-add-modal>
|
||||
{%- else -%}
|
||||
<product-form data-section-id="{{ section.id }}">
|
||||
{%- form 'product',
|
||||
card_product,
|
||||
id: product_form_id,
|
||||
class: 'form',
|
||||
novalidate: 'novalidate',
|
||||
data-type: 'add-to-cart-form'
|
||||
-%}
|
||||
<input
|
||||
type="hidden"
|
||||
name="id"
|
||||
value="{{ card_product.selected_or_first_available_variant.id }}"
|
||||
class="product-variant-id"
|
||||
{% if card_product.selected_or_first_available_variant.available == false %}
|
||||
disabled
|
||||
{% endif %}
|
||||
>
|
||||
<button
|
||||
id="{{ product_form_id }}-submit"
|
||||
type="submit"
|
||||
name="add"
|
||||
class="quick-add__submit button button--full-width button--secondary{% if horizontal_quick_add %} card--horizontal__quick-add{% endif %}"
|
||||
aria-haspopup="dialog"
|
||||
aria-labelledby="{{ product_form_id }}-submit title-{{ section_id }}-{{ card_product.id }}"
|
||||
aria-live="polite"
|
||||
data-sold-out-message="true"
|
||||
{% if card_product.selected_or_first_available_variant.available == false %}
|
||||
disabled
|
||||
{% endif %}
|
||||
>
|
||||
<span>
|
||||
{%- if card_product.selected_or_first_available_variant.available -%}
|
||||
{{ 'products.product.add_to_cart' | t }}
|
||||
{%- else -%}
|
||||
{{ 'products.product.sold_out' | t }}
|
||||
{%- endif -%}
|
||||
</span>
|
||||
<span class="sold-out-message hidden">
|
||||
{{ 'products.product.sold_out' | t }}
|
||||
</span>
|
||||
{%- if horizontal_quick_add -%}
|
||||
<span class="icon-wrap">
|
||||
{{- 'icon-plus.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- render 'loading-spinner' -%}
|
||||
</button>
|
||||
{%- endform -%}
|
||||
</product-form>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{% elsif quick_add == 'bulk' %}
|
||||
{% if card_product.variants_count == 1 %}
|
||||
<quick-add-bulk
|
||||
data-min="{{ card_product.selected_or_first_available_variant.quantity_rule.min }}"
|
||||
id="quick-add-bulk-{{ card_product.selected_or_first_available_variant.id }}-{{ section.id }}"
|
||||
class="quick-add-bulk"
|
||||
data-index="{{ card_product.selected_or_first_available_variant.id }}"
|
||||
>
|
||||
{% if card_product.selected_or_first_available_variant.available == false %}
|
||||
<button
|
||||
id="{{ product_form_id }}-submit"
|
||||
type="submit"
|
||||
name="add"
|
||||
class="quick-add__submit button button--full-width button--secondary"
|
||||
aria-labelledby="{{ product_form_id }}-submit title-{{ section_id }}-{{ card_product.id }}"
|
||||
data-sold-out-message="true"
|
||||
disabled
|
||||
>
|
||||
<span>{{ 'products.product.sold_out' | t }}</span>
|
||||
<span class="sold-out-message hidden">
|
||||
{{ 'products.product.sold_out' | t }}
|
||||
</span>
|
||||
</button>
|
||||
{% else %}
|
||||
{% render 'quantity-input', variant: card_product.selected_or_first_available_variant, min: 0 %}
|
||||
{% endif %}
|
||||
</quick-add-bulk>
|
||||
{% else %}
|
||||
<div class="quick-add no-js-hidden">
|
||||
{%- liquid
|
||||
assign product_form_id = 'quick-add-' | append: section_id | append: card_product.id
|
||||
assign qty_rules = false
|
||||
if card_product.selected_or_first_available_variant.quantity_rule.min > 1 or card_product.selected_or_first_available_variant.quantity_rule.max != null or card_product.selected_or_first_available_variant.quantity_rule.increment > 1
|
||||
assign qty_rules = true
|
||||
endif
|
||||
-%}
|
||||
<modal-opener
|
||||
id="QuickBulk-{{ card_product.id }}-{{ section_id }}"
|
||||
data-modal="#QuickAddBulk-{{ card_product.id }}-{{ section.id }}"
|
||||
>
|
||||
<button
|
||||
id="{{ product_form_id }}-submit"
|
||||
type="submit"
|
||||
name="add"
|
||||
class="quick-add__submit button button--full-width button--secondary"
|
||||
aria-haspopup="dialog"
|
||||
aria-labelledby="{{ product_form_id }}-submit title-{{ section_id }}-{{ card_product.id }}"
|
||||
data-product-url="{{ card_product.url }}"
|
||||
>
|
||||
{{ 'products.product.choose_options' | t }}
|
||||
{%- render 'loading-spinner' -%}
|
||||
</button>
|
||||
</modal-opener>
|
||||
<modal-dialog
|
||||
id="QuickAddBulk-{{ card_product.id }}-{{ section_id }}"
|
||||
class="quick-add-modal color-{{ section.settings.color_scheme }}"
|
||||
>
|
||||
<div
|
||||
role="dialog"
|
||||
aria-label="{{ 'products.product.choose_product_options' | t: product_name: card_product.title | escape }}"
|
||||
aria-modal="true"
|
||||
class="quick-add-modal__content quick-add-modal__content--bulk global-settings-popup"
|
||||
tabindex="-1"
|
||||
>
|
||||
<button
|
||||
id="ModalClose-{{ card_product.id }}"
|
||||
type="button"
|
||||
class="quick-add-modal__toggle"
|
||||
aria-label="{{ 'accessibility.close' | t }}"
|
||||
>
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</button>
|
||||
<div
|
||||
id="QuickAddInfo-{{ card_product.id }}"
|
||||
class="quick-add-modal__content-info quick-add-modal__content-info--bulk"
|
||||
>
|
||||
<div class="quick-add__content-info__media">
|
||||
<div class="quick-add__info">
|
||||
{%- if card_product.featured_media -%}
|
||||
<div
|
||||
class="quick-add__product-media"
|
||||
>
|
||||
<div class="quick-add__product-container global-media-settings">
|
||||
{% comment %}theme-check-disable ImgLazyLoading{% endcomment %}
|
||||
<img
|
||||
srcset="
|
||||
{%- if card_product.featured_media.width >= 165 -%}{{ card_product.featured_media | image_url: width: 165 }} 165w,{%- endif -%}
|
||||
{%- if card_product.featured_media.width >= 360 -%}{{ card_product.featured_media | image_url: width: 360 }} 360w,{%- endif -%}
|
||||
{%- if card_product.featured_media.width >= 533 -%}{{ card_product.featured_media | image_url: width: 533 }} 533w,{%- endif -%}
|
||||
{%- if card_product.featured_media.width >= 720 -%}{{ card_product.featured_media | image_url: width: 720 }} 720w,{%- endif -%}
|
||||
{%- if card_product.featured_media.width >= 940 -%}{{ card_product.featured_media | image_url: width: 940 }} 940w,{%- endif -%}
|
||||
{%- if card_product.featured_media.width >= 1066 -%}{{ card_product.featured_media | image_url: width: 1066 }} 1066w,{%- endif -%}
|
||||
{{ card_product.featured_media | image_url }} {{ card_product.featured_media.width }}w
|
||||
"
|
||||
src="{{ card_product.featured_media | image_url: width: 533 }}"
|
||||
sizes="(min-width: {{ settings.page_width }}px) {{ settings.page_width | minus: 130 | divided_by: 4 }}px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)"
|
||||
alt="{{ card_product.featured_media.alt | escape }}"
|
||||
class="motion-reduce"
|
||||
{% unless lazy_load == false %}
|
||||
loading="lazy"
|
||||
{% endunless %}
|
||||
width="{{ card_product.featured_media.width }}"
|
||||
height="{{ card_product.featured_media.height }}"
|
||||
>
|
||||
{% comment %}theme-check-enable ImgLazyLoading{% endcomment %}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<a
|
||||
{% if card_product == blank %}
|
||||
role="link" aria-disabled="true"
|
||||
{% else %}
|
||||
href="{{ card_product.url }}"
|
||||
{% endif %}
|
||||
class="link product__view-details animate-arrow small-hide medium-hide"
|
||||
>
|
||||
{{ 'products.product.view_full_details' | t -}}
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="quick-add-modal__content-info--bulk-details large-up-hide">
|
||||
<a href="{{ card_product.url }}" class="full-unstyled-link">
|
||||
<h3>{{ card_product.title | escape }}</h3>
|
||||
</a>
|
||||
{% render 'price', product: card_product, price_class: '', show_compare_at_price: true %}
|
||||
{%- if card_product.quantity_price_breaks_configured? -%}
|
||||
<div class="card__information-volume-pricing-note">
|
||||
<span class="caption">{{ 'products.product.volume_pricing.note' | t }}</span>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="quick-add-modal__content-info--bulk-details small-hide medium-hide">
|
||||
<a href="{{ card_product.url }}" class="full-unstyled-link">
|
||||
<h3 class="h2">
|
||||
{{ card_product.title | escape }}
|
||||
</h3>
|
||||
</a>
|
||||
{% render 'price', product: card_product, price_class: '', show_compare_at_price: true %}
|
||||
{%- if card_product.quantity_price_breaks_configured? -%}
|
||||
<div class="card__information-volume-pricing-note">
|
||||
<span class="caption">{{ 'products.product.volume_pricing.note' | t }}</span>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<bulk-modal
|
||||
id="QuickBulkModal-{{ card_product.id }}-{{ section_id }}"
|
||||
data-url="{{ card_product.url }}"
|
||||
data-section-id="{{ section_id }}"
|
||||
data-product-id="{{ card_product.id }}"
|
||||
>
|
||||
</bulk-modal>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</modal-dialog>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div class="card__badge {{ settings.badge_position }}">
|
||||
{%- if card_product.available == false -%}
|
||||
<span
|
||||
id="Badge-{{ section_id }}-{{ card_product.id }}"
|
||||
class="badge badge--bottom-left color-{{ settings.sold_out_badge_color_scheme }}"
|
||||
>
|
||||
{{- 'products.product.sold_out' | t -}}
|
||||
</span>
|
||||
{%- elsif card_product.compare_at_price > card_product.price and card_product.available -%}
|
||||
<span
|
||||
id="Badge-{{ section_id }}-{{ card_product.id }}"
|
||||
class="badge badge--bottom-left color-{{ settings.sale_badge_color_scheme }}"
|
||||
>
|
||||
{{- 'products.product.on_sale' | t -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</product-component>
|
||||
{%- else -%}
|
||||
{%- liquid
|
||||
assign ratio = 1
|
||||
assign placeholder = true
|
||||
if media_aspect_ratio == 'portrait'
|
||||
assign ratio = 0.8
|
||||
endif
|
||||
-%}
|
||||
<div class="card-wrapper product-card-wrapper underline-links-hover">
|
||||
<div
|
||||
class="
|
||||
card card--{{ settings.card_style }}
|
||||
{% if extend_height %} card--extend-height{% endif %}
|
||||
{% if image_shape and image_shape != 'default' %} card--shape{% endif %}
|
||||
{% if settings.card_style == 'card' %} color-{{ settings.card_color_scheme }} gradient{% endif %}
|
||||
"
|
||||
style="--ratio-percent: {{ 1 | divided_by: ratio | times: 100 }}%;"
|
||||
>
|
||||
<div
|
||||
class="card__inner{% if settings.card_style == 'standard' %} color-{{ settings.card_color_scheme }} gradient{% endif %} ratio"
|
||||
>
|
||||
<div
|
||||
class="card__media {% if image_shape and image_shape != 'default' %} shape--{{ image_shape }} color-{{ settings.card_color_scheme }} gradient{% endif %}"
|
||||
>
|
||||
<div
|
||||
class="media media--transparent"
|
||||
>
|
||||
{%- if placeholder_image -%}
|
||||
{{ placeholder_image | placeholder_svg_tag: 'placeholder-svg' }}
|
||||
{%- else -%}
|
||||
{{ 'product-apparel-2' | placeholder_svg_tag: 'placeholder-svg' }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card__content">
|
||||
<div class="card__information">
|
||||
<h3 class="card__heading card__heading--placeholder{% if settings.card_style == 'standard' %} h5{% endif %}">
|
||||
<a role="link" aria-disabled="true" class="full-unstyled-link">
|
||||
{{ 'onboarding.product_title' | t }}
|
||||
</a>
|
||||
</h3>
|
||||
<div class="card-information">
|
||||
{%- if show_vendor -%}
|
||||
<span class="visually-hidden">{{ 'accessibility.vendor' | t }}</span>
|
||||
<div class="caption-with-letter-spacing light">{{ 'products.product.vendor' | t }}</div>
|
||||
{%- endif -%}
|
||||
{% render 'price', placeholder: placeholder, show_compare_at_price: true %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
@@ -0,0 +1,128 @@
|
||||
{% comment %}
|
||||
Renders a cart disclosure indicator when the product has a disclosure configured for the cart surface.
|
||||
|
||||
Accepts:
|
||||
- product: {Object} Product object
|
||||
- modal_id: {String} Unique modal id for this cart line
|
||||
{% endcomment %}
|
||||
|
||||
{%- liquid
|
||||
assign disclosures = product.metafields.shopify.disclosure.value
|
||||
assign cart_disclosures_count = 0
|
||||
|
||||
if disclosures != blank
|
||||
for disclosure in disclosures
|
||||
assign surfaces = disclosure.display_preferences.value.surfaces
|
||||
|
||||
if surfaces contains 'cart'
|
||||
assign cart_disclosures_count = cart_disclosures_count | plus: 1
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
-%}
|
||||
|
||||
{%- if cart_disclosures_count > 0 and modal_id != blank -%}
|
||||
{%- capture cart_disclosure_rows -%}
|
||||
{%- for disclosure in disclosures -%}
|
||||
{%- assign surfaces = disclosure.display_preferences.value.surfaces -%}
|
||||
|
||||
{%- if surfaces contains 'cart' -%}
|
||||
{%- assign title = disclosure.title.value -%}
|
||||
{%- assign symbol = disclosure.symbol.value -%}
|
||||
|
||||
<span class="cart-item__disclosure-tooltip-row">
|
||||
<span class="cart-item__disclosure-tooltip-symbol-slot">
|
||||
{%- if symbol != blank -%}
|
||||
<img
|
||||
src="{{ symbol | image_url: width: 32 }}"
|
||||
alt=""
|
||||
class="cart-item__disclosure-tooltip-symbol"
|
||||
width="40"
|
||||
height="31"
|
||||
loading="lazy"
|
||||
>
|
||||
{%- endif -%}
|
||||
</span>
|
||||
<span class="cart-item__disclosure-tooltip-title">
|
||||
{{- title | escape -}}
|
||||
</span>
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endcapture -%}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="cart-item__disclosure"
|
||||
aria-controls="{{ modal_id }}-dialog"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="dialog"
|
||||
aria-label="{{ 'sections.cart.product_disclosure' | t }}"
|
||||
>
|
||||
<span class="cart-item__disclosure-indicator svg-wrapper" aria-hidden="true">
|
||||
{{- 'icon-warning.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="cart-item__disclosure-tooltip" aria-hidden="true">
|
||||
{{- cart_disclosure_rows -}}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<cart-disclosure-modal id="{{ modal_id }}" class="cart-disclosure-modal">
|
||||
<div
|
||||
id="{{ modal_id }}-dialog"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="{{ modal_id }}-title"
|
||||
class="cart-disclosure-modal__content"
|
||||
tabindex="-1"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="cart-disclosure-modal__close"
|
||||
data-cart-disclosure-close
|
||||
aria-label="{{ 'accessibility.close' | t }}"
|
||||
>
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</button>
|
||||
<h2 id="{{ modal_id }}-title" class="cart-disclosure-modal__title">
|
||||
{{- 'sections.cart.product_disclosures' | t -}}
|
||||
</h2>
|
||||
<div class="cart-disclosure-modal__items">
|
||||
{%- for disclosure in disclosures -%}
|
||||
{%- assign surfaces = disclosure.display_preferences.value.surfaces -%}
|
||||
|
||||
{%- if surfaces contains 'cart' -%}
|
||||
{%- assign title = disclosure.title.value -%}
|
||||
{%- assign symbol = disclosure.symbol.value -%}
|
||||
{%- assign content = disclosure.content -%}
|
||||
|
||||
<div class="cart-disclosure-modal__item">
|
||||
{%- if title != blank or symbol != blank -%}
|
||||
<div class="cart-disclosure-modal__item-header">
|
||||
<span class="cart-disclosure-modal__symbol-slot">
|
||||
{%- if symbol != blank -%}
|
||||
<img
|
||||
src="{{ symbol | image_url: width: 40 }}"
|
||||
alt=""
|
||||
class="cart-disclosure-modal__symbol"
|
||||
width="40"
|
||||
height="31"
|
||||
loading="lazy"
|
||||
>
|
||||
{%- endif -%}
|
||||
</span>
|
||||
{%- if title != blank -%}
|
||||
<h3 class="cart-disclosure-modal__item-title">{{ title | escape }}</h3>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<div class="cart-disclosure-modal__item-content">
|
||||
{{ content | metafield_tag }}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
</div>
|
||||
</cart-disclosure-modal>
|
||||
{%- endif -%}
|
||||
@@ -0,0 +1,594 @@
|
||||
{% comment %}
|
||||
Renders cart drawer
|
||||
|
||||
Usage:
|
||||
{% render 'cart-drawer' %}
|
||||
{% endcomment %}
|
||||
|
||||
{{ 'quantity-popover.css' | asset_url | stylesheet_tag }}
|
||||
{{ 'component-card.css' | asset_url | stylesheet_tag }}
|
||||
|
||||
<script src="{{ 'cart.js' | asset_url }}" defer="defer"></script>
|
||||
<script src="{{ 'quantity-popover.js' | asset_url }}" defer="defer"></script>
|
||||
|
||||
<style>
|
||||
.drawer {
|
||||
visibility: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
<cart-drawer class="drawer{% if cart == empty %} is-empty{% endif %}">
|
||||
<div id="CartDrawer" class="cart-drawer">
|
||||
<div id="CartDrawer-Overlay" class="cart-drawer__overlay"></div>
|
||||
<div
|
||||
class="drawer__inner gradient color-{{ settings.cart_color_scheme }}"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label="{{ 'sections.cart.title' | t }}"
|
||||
tabindex="-1"
|
||||
>
|
||||
{%- if cart == empty -%}
|
||||
<div class="drawer__inner-empty">
|
||||
<div class="cart-drawer__warnings center{% if settings.cart_drawer_collection != blank %} cart-drawer__warnings--has-collection{% endif %}">
|
||||
<div class="cart-drawer__empty-content">
|
||||
<h2 class="cart__empty-text">{{ 'sections.cart.empty' | t }}</h2>
|
||||
<button
|
||||
class="drawer__close"
|
||||
type="button"
|
||||
onclick="this.closest('cart-drawer').close()"
|
||||
aria-label="{{ 'accessibility.close' | t }}"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
<a href="{{ routes.all_products_collection_url }}" class="button">
|
||||
{{ 'general.continue_shopping' | t }}
|
||||
</a>
|
||||
|
||||
{%- if shop.customer_accounts_enabled and customer == null -%}
|
||||
<p class="cart__login-title h3">{{ 'sections.cart.login.title' | t }}</p>
|
||||
<p class="cart__login-paragraph">
|
||||
{{ 'sections.cart.login.paragraph_html' | t: link: routes.account_login_url }}
|
||||
</p>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</div>
|
||||
{%- if settings.cart_drawer_collection != blank -%}
|
||||
<div class="cart-drawer__collection">
|
||||
{% render 'card-collection', card_collection: settings.cart_drawer_collection, columns: 1 %}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<div class="drawer__header">
|
||||
<h2 class="drawer__heading">{{ 'sections.cart.title' | t }}</h2>
|
||||
<button
|
||||
class="drawer__close"
|
||||
type="button"
|
||||
onclick="this.closest('cart-drawer').close()"
|
||||
aria-label="{{ 'accessibility.close' | t }}"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<cart-drawer-items
|
||||
view-event-payload="{{ cart | standard_event_data: 'view', context: 'dialog' | escape }}"
|
||||
view-event-trigger="manual"
|
||||
{% if cart == empty %}
|
||||
class=" is-empty"
|
||||
{% endif %}
|
||||
>
|
||||
<form
|
||||
action="{{ routes.cart_url }}"
|
||||
id="CartDrawer-Form"
|
||||
class="cart__contents cart-drawer__form"
|
||||
method="post"
|
||||
>
|
||||
<div id="CartDrawer-CartItems" class="drawer__contents js-contents">
|
||||
{%- if cart != empty -%}
|
||||
<div class="drawer__cart-items-wrapper">
|
||||
<table class="cart-items" role="table">
|
||||
<thead role="rowgroup">
|
||||
<tr role="row">
|
||||
<th id="CartDrawer-ColumnProductImage" role="columnheader">
|
||||
<span class="visually-hidden">{{ 'sections.cart.headings.image' | t }}</span>
|
||||
</th>
|
||||
<th
|
||||
id="CartDrawer-ColumnProduct"
|
||||
class="caption-with-letter-spacing"
|
||||
scope="col"
|
||||
role="columnheader"
|
||||
>
|
||||
{{ 'sections.cart.headings.product' | t }}
|
||||
</th>
|
||||
<th
|
||||
id="CartDrawer-ColumnTotal"
|
||||
class="right caption-with-letter-spacing"
|
||||
scope="col"
|
||||
role="columnheader"
|
||||
>
|
||||
{{ 'sections.cart.headings.total' | t }}
|
||||
</th>
|
||||
<th id="CartDrawer-ColumnQuantity" role="columnheader">
|
||||
<span class="visually-hidden">{{ 'sections.cart.headings.quantity' | t }}</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody role="rowgroup">
|
||||
{%- for item in cart.items -%}
|
||||
<tr
|
||||
id="CartDrawer-Item-{{ item.index | plus: 1 }}"
|
||||
class="cart-item{% if item.parent_relationship.parent != null %} cart-item__nested-line{% endif %}"
|
||||
role="row"
|
||||
{% if item.parent_relationship.parent != null %}
|
||||
aria-label="{{- 'products.product.nested_label' | t: title: item.product.title, parent_title: item.parent_relationship.parent.title | escape -}}"
|
||||
{% endif %}
|
||||
>
|
||||
<td
|
||||
class="cart-item__media"
|
||||
role="cell"
|
||||
headers="CartDrawer-ColumnProductImage"
|
||||
>
|
||||
{% if item.image %}
|
||||
{% comment %} Leave empty space due to a:empty CSS display: none rule {% endcomment %}
|
||||
<a href="{{ item.url }}" class="cart-item__link" tabindex="-1" aria-hidden="true"> </a>
|
||||
<img
|
||||
class="cart-item__image"
|
||||
src="{{ item.image | image_url: width: 300 }}"
|
||||
alt="{{ item.image.alt | escape }}"
|
||||
loading="lazy"
|
||||
width="150"
|
||||
height="{{ 150 | divided_by: item.image.aspect_ratio | ceil }}"
|
||||
>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<td class="cart-item__details" role="cell" headers="CartDrawer-ColumnProduct">
|
||||
{%- if settings.show_vendor -%}
|
||||
<p class="caption-with-letter-spacing light">{{ item.product.vendor }}</p>
|
||||
{%- endif -%}
|
||||
|
||||
<div class="cart-item__title">
|
||||
<a href="{{ item.url }}" class="cart-item__name h4 break">
|
||||
{{- item.product.title | escape -}}
|
||||
</a>
|
||||
{%- assign cart_disclosure_modal_id = 'CartDisclosureModal-drawer-' | append: item.key | replace: ':', '-' -%}
|
||||
{%- render 'cart-disclosure-indicator',
|
||||
product: item.product,
|
||||
modal_id: cart_disclosure_modal_id
|
||||
-%}
|
||||
</div>
|
||||
|
||||
{%- if item.original_price != item.final_price -%}
|
||||
<div class="cart-item__discounted-prices">
|
||||
<span class="visually-hidden">
|
||||
{{ 'products.product.price.regular_price' | t }}
|
||||
</span>
|
||||
<s class="cart-item__old-price product-option">
|
||||
{{- item.original_price | money -}}
|
||||
</s>
|
||||
<span class="visually-hidden">
|
||||
{{ 'products.product.price.sale_price' | t }}
|
||||
</span>
|
||||
<strong class="cart-item__final-price product-option">
|
||||
{{ item.final_price | money }}
|
||||
</strong>
|
||||
</div>
|
||||
{%- else -%}
|
||||
<div class="product-option">
|
||||
{{ item.original_price | money }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if item.product.has_only_default_variant == false
|
||||
or item.properties.size != 0
|
||||
or item.selling_plan_allocation != null
|
||||
-%}
|
||||
<dl>
|
||||
{%- if item.product.has_only_default_variant == false -%}
|
||||
{%- for option in item.options_with_values -%}
|
||||
<div class="product-option">
|
||||
<dt>{{ option.name }}:</dt>
|
||||
<dd>
|
||||
{{ option.value -}}
|
||||
{%- unless forloop.last %}, {% endunless %}
|
||||
</dd>
|
||||
</div>
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
|
||||
{%- for property in item.properties -%}
|
||||
{%- assign property_first_char = property.first | slice: 0 -%}
|
||||
{%- if property.last != blank and property_first_char != '_' -%}
|
||||
<div class="product-option">
|
||||
<dt>{{ property.first }}:</dt>
|
||||
<dd>
|
||||
{%- if property.last contains '/uploads/' -%}
|
||||
<a
|
||||
href="{{ property.last }}"
|
||||
class="link"
|
||||
target="_blank"
|
||||
aria-describedby="a11y-new-window-message"
|
||||
>
|
||||
{{ property.last | split: '/' | last }}
|
||||
</a>
|
||||
{%- else -%}
|
||||
{{ property.last }}
|
||||
{%- endif -%}
|
||||
</dd>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</dl>
|
||||
|
||||
<p class="product-option">{{ item.selling_plan_allocation.selling_plan.name }}</p>
|
||||
{%- endif -%}
|
||||
|
||||
<ul
|
||||
class="discounts list-unstyled"
|
||||
role="list"
|
||||
aria-label="{{ 'customer.order.discount' | t }}"
|
||||
>
|
||||
{%- for discount in item.line_level_discount_allocations -%}
|
||||
<li class="discounts__discount">
|
||||
{{- 'icon-discount.svg' | inline_asset_content -}}
|
||||
{{ discount.discount_application.title }}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</td>
|
||||
|
||||
<td class="cart-item__totals right" role="cell" headers="CartDrawer-ColumnTotal">
|
||||
{%- render 'loading-spinner' -%}
|
||||
<div class="cart-item__price-wrapper">
|
||||
{%- if item.original_line_price != item.final_line_price -%}
|
||||
<div class="cart-item__discounted-prices">
|
||||
<span class="visually-hidden">
|
||||
{{ 'products.product.price.regular_price' | t }}
|
||||
</span>
|
||||
<s class="cart-item__old-price price price--end">
|
||||
{{ item.original_line_price | money }}
|
||||
</s>
|
||||
<span class="visually-hidden">
|
||||
{{ 'products.product.price.sale_price' | t }}
|
||||
</span>
|
||||
<span class="price price--end">
|
||||
{{ item.final_line_price | money }}
|
||||
</span>
|
||||
</div>
|
||||
{%- else -%}
|
||||
<span class="price price--end">
|
||||
{{ item.original_line_price | money }}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if item.variant.available and item.unit_price_measurement -%}
|
||||
{% render 'unit-price',
|
||||
price: item.unit_price,
|
||||
measurement: item.unit_price_measurement
|
||||
%}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</td>
|
||||
{%- liquid
|
||||
assign has_qty_rules = false
|
||||
if item.variant.quantity_rule.increment > 1 or item.variant.quantity_rule.min > 1 or item.variant.quantity_rule.max != null
|
||||
assign has_qty_rules = true
|
||||
endif
|
||||
|
||||
assign has_vol_pricing = false
|
||||
if item.variant.quantity_price_breaks.size > 0
|
||||
assign has_vol_pricing = true
|
||||
endif
|
||||
-%}
|
||||
<td
|
||||
class="cart-item__quantity {% if has_qty_rules or has_vol_pricing %} cart-item__quantity--info{% endif %}"
|
||||
role="cell"
|
||||
headers="CartDrawer-ColumnQuantity"
|
||||
>
|
||||
<quantity-popover>
|
||||
<div class="cart-item__quantity-wrapper quantity-popover-wrapper">
|
||||
<div class="quantity-popover-container{% if has_qty_rules or has_vol_pricing %} quantity-popover-container--hover{% endif %}">
|
||||
<quantity-input class="quantity cart-quantity">
|
||||
<button
|
||||
class="quantity__button"
|
||||
name="minus"
|
||||
type="button"
|
||||
{% if item.instructions and item.instructions.can_update_quantity == false %}
|
||||
disabled
|
||||
{% endif %}
|
||||
>
|
||||
<span class="visually-hidden">
|
||||
{{-
|
||||
'products.product.quantity.decrease'
|
||||
| t: product: item.product.title
|
||||
| escape
|
||||
-}}
|
||||
</span>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-minus.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
<input
|
||||
class="quantity__input"
|
||||
type="number"
|
||||
data-quantity-variant-id="{{ item.variant.id }}"
|
||||
data-quantity-line-key="{{ item.key }}"
|
||||
name="updates[]"
|
||||
value="{{ item.quantity }}"
|
||||
{% # theme-check-disable %}
|
||||
data-cart-quantity="{{ cart | item_count_for_variant: item.variant.id }}"
|
||||
min="0"
|
||||
data-min="{{ item.variant.quantity_rule.min }}"
|
||||
{% if item.variant.quantity_rule.max != null %}
|
||||
max="{{ item.variant.quantity_rule.max }}"
|
||||
{% endif %}
|
||||
step="{{ item.variant.quantity_rule.increment }}"
|
||||
{% # theme-check-enable %}
|
||||
aria-label="{{ 'products.product.quantity.input_label' | t: product: item.product.title | escape }}"
|
||||
id="Drawer-quantity-{{ item.index | plus: 1 }}"
|
||||
data-index="{{ item.index | plus: 1 }}"
|
||||
{% if item.instructions and item.instructions.can_update_quantity == false %}
|
||||
disabled
|
||||
{% endif %}
|
||||
>
|
||||
<button
|
||||
class="quantity__button"
|
||||
name="plus"
|
||||
type="button"
|
||||
{% if item.instructions and item.instructions.can_update_quantity == false %}
|
||||
disabled
|
||||
{% endif %}
|
||||
>
|
||||
<span class="visually-hidden">
|
||||
{{-
|
||||
'products.product.quantity.increase'
|
||||
| t: product: item.product.title
|
||||
| escape
|
||||
-}}
|
||||
</span>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-plus.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
</quantity-input>
|
||||
</div>
|
||||
<cart-remove-button
|
||||
id="CartDrawer-Remove-{{ item.index | plus: 1 }}"
|
||||
data-index="{{ item.index | plus: 1 }}"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="button button--tertiary cart-remove-button"
|
||||
aria-label="{{ 'sections.cart.remove_title' | t: title: item.title | escape }}"
|
||||
data-variant-id="{{ item.variant.id }}"
|
||||
{% if item.instructions and item.instructions.can_remove == false %}
|
||||
class="hidden"
|
||||
{% endif %}
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-remove.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
</cart-remove-button>
|
||||
</div>
|
||||
{%- if has_qty_rules or has_vol_pricing -%}
|
||||
<button
|
||||
type="button"
|
||||
class="quantity-popover__info-button quantity-popover__info-button--icon-with-label button button--tertiary"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-info.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span>
|
||||
{%- if has_vol_pricing -%}
|
||||
{{ 'products.product.volume_pricing.note' | t }}
|
||||
{%- elsif has_qty_rules -%}
|
||||
{{ 'products.product.quantity.note' | t }}
|
||||
{%- endif -%}
|
||||
</span>
|
||||
</button>
|
||||
{%- endif -%}
|
||||
{%- if has_vol_pricing or has_qty_rules -%}
|
||||
<div
|
||||
class="cart-items__info global-settings-popup quantity-popover__info"
|
||||
tabindex="-1"
|
||||
hidden
|
||||
>
|
||||
{%- if has_qty_rules == false -%}
|
||||
<span class="volume-pricing-label caption">
|
||||
{{- 'products.product.volume_pricing.title' | t -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
<div class="quantity__rules caption">
|
||||
{%- if item.variant.quantity_rule.increment > 1 -%}
|
||||
<span class="divider">
|
||||
{{-
|
||||
'products.product.quantity.multiples_of'
|
||||
| t: quantity: item.variant.quantity_rule.increment
|
||||
-}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- if item.variant.quantity_rule.min > 1 -%}
|
||||
<span class="divider">
|
||||
{{-
|
||||
'products.product.quantity.min_of'
|
||||
| t: quantity: item.variant.quantity_rule.min
|
||||
-}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- if item.variant.quantity_rule.max != null -%}
|
||||
<span class="divider">
|
||||
{{-
|
||||
'products.product.quantity.max_of'
|
||||
| t: quantity: item.variant.quantity_rule.max
|
||||
-}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<button
|
||||
class="button-close button button--tertiary"
|
||||
type="button"
|
||||
aria-label="{{ 'accessibility.close' | t }}"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
{%- if item.variant.quantity_price_breaks.size > 0 -%}
|
||||
<volume-pricing class="parent-display">
|
||||
<ul class="list-unstyled">
|
||||
<li>
|
||||
<span>{{ item.variant.quantity_rule.min }}+</span>
|
||||
<span>{{ item.variant.price | money_with_currency }}/ea</span>
|
||||
</li>
|
||||
{%- for price_break in item.variant.quantity_price_breaks -%}
|
||||
<li>
|
||||
<span>
|
||||
{{- price_break.minimum_quantity -}}
|
||||
<span aria-hidden="true">+</span></span
|
||||
>
|
||||
<span>{{ price_break.price | money_with_currency }}/ea</span>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</volume-pricing>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<div
|
||||
id="CartDrawer-LineItemError-{{ item.index | plus: 1 }}"
|
||||
class="cart-item__error"
|
||||
role="alert"
|
||||
>
|
||||
<small class="cart-item__error-text"></small>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-error.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</div>
|
||||
</quantity-popover>
|
||||
</td>
|
||||
</tr>
|
||||
{%- endfor -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<p id="CartDrawer-LiveRegionText" class="visually-hidden" role="status"></p>
|
||||
<p id="CartDrawer-LineItemStatus" class="visually-hidden" aria-hidden="true" role="status">
|
||||
{{ 'accessibility.loading' | t }}
|
||||
</p>
|
||||
</div>
|
||||
<div id="CartDrawer-CartErrors" role="alert"></div>
|
||||
</form>
|
||||
</cart-drawer-items>
|
||||
<div class="drawer__footer">
|
||||
{%- if settings.show_cart_note -%}
|
||||
<details id="Details-CartDrawer">
|
||||
<summary>
|
||||
<span class="summary__title">
|
||||
{{ 'sections.cart.note' | t }}
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</summary>
|
||||
<cart-note class="cart__note field">
|
||||
<label class="visually-hidden" for="CartDrawer-Note">{{ 'sections.cart.note' | t }}</label>
|
||||
<textarea
|
||||
id="CartDrawer-Note"
|
||||
class="text-area text-area--resize-vertical field__input"
|
||||
name="note"
|
||||
placeholder="{{ 'sections.cart.note' | t }}"
|
||||
>{{ cart.note }}</textarea>
|
||||
</cart-note>
|
||||
</details>
|
||||
{%- endif -%}
|
||||
|
||||
<!-- Start blocks -->
|
||||
<!-- Subtotals -->
|
||||
|
||||
<div class="cart-drawer__footer" {{ block.shopify_attributes }}>
|
||||
<div>
|
||||
{%- if cart.cart_level_discount_applications.size > 0 -%}
|
||||
<ul class="discounts list-unstyled" role="list" aria-label="{{ 'customer.order.discount' | t }}">
|
||||
{%- for discount in cart.cart_level_discount_applications -%}
|
||||
<li class="discounts__discount discounts__discount--end">
|
||||
{{- 'icon-discount.svg' | inline_asset_content -}}
|
||||
{{ discount.title | escape }}
|
||||
(-{{ discount.total_allocated_amount | money }})
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
|
||||
<div class="totals" role="status">
|
||||
<h2 class="totals__total">{{ 'sections.cart.estimated_total' | t }}</h2>
|
||||
<p class="totals__total-value">{{ cart.total_price | money_with_currency }}</p>
|
||||
</div>
|
||||
|
||||
<small class="tax-note caption-large rte">
|
||||
{%- if cart.duties_included and cart.taxes_included -%}
|
||||
{%- if shop.shipping_policy.body == blank -%}
|
||||
{{ 'sections.cart.duties_and_taxes_included_shipping_at_checkout_without_policy' | t }}
|
||||
{%- else -%}
|
||||
{{
|
||||
'sections.cart.duties_and_taxes_included_shipping_at_checkout_with_policy_html'
|
||||
| t: link: shop.shipping_policy.url
|
||||
}}
|
||||
{%- endif -%}
|
||||
{%- elsif cart.duties_included == false and cart.taxes_included -%}
|
||||
{%- if shop.shipping_policy.body == blank -%}
|
||||
{{ 'sections.cart.taxes_included_shipping_at_checkout_without_policy' | t }}
|
||||
{%- else -%}
|
||||
{{
|
||||
'sections.cart.taxes_included_shipping_at_checkout_with_policy_html'
|
||||
| t: link: shop.shipping_policy.url
|
||||
}}
|
||||
{%- endif -%}
|
||||
{%- elsif cart.duties_included and cart.taxes_included == false -%}
|
||||
{%- if shop.shipping_policy.body == blank -%}
|
||||
{{ 'sections.cart.duties_included_taxes_at_checkout_shipping_at_checkout_without_policy' | t }}
|
||||
{%- else -%}
|
||||
{{
|
||||
'sections.cart.duties_included_taxes_at_checkout_shipping_at_checkout_with_policy_html'
|
||||
| t: link: shop.shipping_policy.url
|
||||
}}
|
||||
{%- endif -%}
|
||||
{%- elsif cart.duties_included == false and cart.taxes_included == false -%}
|
||||
{%- if shop.shipping_policy.body == blank -%}
|
||||
{{ 'sections.cart.taxes_at_checkout_shipping_at_checkout_without_policy' | t }}
|
||||
{%- else -%}
|
||||
{{
|
||||
'sections.cart.taxes_at_checkout_shipping_at_checkout_with_policy_html'
|
||||
| t: link: shop.shipping_policy.url
|
||||
}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- CTAs -->
|
||||
|
||||
<div class="cart__ctas" {{ block.shopify_attributes }}>
|
||||
<button
|
||||
type="submit"
|
||||
id="CartDrawer-Checkout"
|
||||
class="cart__checkout-button button"
|
||||
name="checkout"
|
||||
form="CartDrawer-Form"
|
||||
{% if cart == empty %}
|
||||
disabled
|
||||
{% endif %}
|
||||
>
|
||||
{{ 'sections.cart.checkout' | t }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</cart-drawer>
|
||||
@@ -0,0 +1,60 @@
|
||||
{% comment %}
|
||||
Renders cart notification
|
||||
|
||||
Accepts:
|
||||
- color_scheme: {String} sets the color scheme of the notification (optional)
|
||||
- desktop_menu_type: {String} passes the desktop menu type which allows us to use the right css class (optional)
|
||||
|
||||
Usage:
|
||||
{% render 'cart-notification' %}
|
||||
{% endcomment %}
|
||||
|
||||
<cart-notification>
|
||||
<div class="cart-notification-wrapper{% if desktop_menu_type != 'drawer' %} page-width{% endif %}">
|
||||
<div
|
||||
id="cart-notification"
|
||||
class="cart-notification focus-inset{% if color_scheme %} color-{{ color_scheme }} gradient{% endif %}"
|
||||
aria-modal="true"
|
||||
aria-label="{{ 'general.cart.item_added' | t }}"
|
||||
role="dialog"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div class="cart-notification__header">
|
||||
<h2 class="cart-notification__heading caption-large text-body">
|
||||
{{- 'icon-checkmark.svg' | inline_asset_content -}}
|
||||
{{ 'general.cart.item_added' | t }}
|
||||
</h2>
|
||||
<button
|
||||
type="button"
|
||||
class="cart-notification__close modal__close-button link link--text focus-inset"
|
||||
aria-label="{{ 'accessibility.close' | t }}"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div id="cart-notification-product" class="cart-notification-product"></div>
|
||||
<div class="cart-notification__links">
|
||||
<a
|
||||
href="{{ routes.cart_url }}"
|
||||
id="cart-notification-button"
|
||||
class="button button--secondary button--full-width"
|
||||
>
|
||||
{{- 'general.cart.view_empty_cart' | t -}}
|
||||
</a>
|
||||
<form action="{{ routes.cart_url }}" method="post" id="cart-notification-form">
|
||||
<button class="button button--primary button--full-width" name="checkout">
|
||||
{{ 'sections.cart.checkout' | t }}
|
||||
</button>
|
||||
</form>
|
||||
<button type="button" class="link button-label">{{ 'general.continue_shopping' | t }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</cart-notification>
|
||||
{% style %}
|
||||
.cart-notification {
|
||||
display: none;
|
||||
}
|
||||
{% endstyle %}
|
||||
@@ -0,0 +1,156 @@
|
||||
{%- comment -%}
|
||||
Renders the country picker for the localization form
|
||||
|
||||
Accepts:
|
||||
- localPosition: pass in the position in which the form is coming up to create specific IDs
|
||||
{%- endcomment -%}
|
||||
|
||||
{%- liquid
|
||||
assign currencies = localization.available_countries | map: 'currency' | map: 'iso_code' | uniq
|
||||
assign popular_countries = localization.available_countries | where: 'popular?' | sort: 'name'
|
||||
|
||||
assign show_country_filter = false
|
||||
if localization.available_countries.size > 9
|
||||
assign show_country_filter = true
|
||||
endif
|
||||
|
||||
assign show_popular_countries = false
|
||||
if localization.available_countries.size > 9 and popular_countries.size > 1
|
||||
assign show_popular_countries = true
|
||||
endif
|
||||
|
||||
assign show_currencies = false
|
||||
if currencies.size > 1
|
||||
assign show_currencies = true
|
||||
endif
|
||||
%}
|
||||
|
||||
<div class="disclosure">
|
||||
<button
|
||||
type="button"
|
||||
class="disclosure__button localization-form__select localization-selector link link--text caption-large"
|
||||
aria-expanded="false"
|
||||
aria-controls="{{ localPosition }}-country-results"
|
||||
aria-describedby="{{ localPosition }}Label"
|
||||
>
|
||||
<span>
|
||||
{{- localization.country.name }} |
|
||||
{{ localization.country.currency.iso_code }}
|
||||
{{ localization.country.currency.symbol -}}
|
||||
</span>
|
||||
{{ 'icon-caret.svg' | inline_asset_content }}
|
||||
</button>
|
||||
<div class="disclosure__list-wrapper country-selector" hidden>
|
||||
<div class="country-filter{% unless show_country_filter %} country-filter--no-padding{% endunless %}">
|
||||
{% if show_country_filter %}
|
||||
<div class="field">
|
||||
<input
|
||||
class="country-filter__input field__input"
|
||||
id="country-filter-input"
|
||||
type="search"
|
||||
name="country_filter"
|
||||
value=""
|
||||
placeholder="{{ 'localization.search' | t }}"
|
||||
role="combobox"
|
||||
aria-owns="country-results"
|
||||
aria-controls="country-results"
|
||||
aria-haspopup="listbox"
|
||||
aria-autocomplete="list"
|
||||
autocorrect="off"
|
||||
autocomplete="off"
|
||||
autocapitalize="off"
|
||||
spellcheck="false"
|
||||
>
|
||||
<label class="field__label" for="country-filter-input">{{ 'localization.search' | t }}</label>
|
||||
<button
|
||||
type="reset"
|
||||
class="country-filter__reset-button field__button hidden"
|
||||
aria-label="{{ 'general.search.reset' | t }}"
|
||||
>
|
||||
{{- 'icon-reset.svg' | inline_asset_content -}}
|
||||
</button>
|
||||
<div class="country-filter__search-icon field__button motion-reduce">
|
||||
{{- 'icon-search.svg' | inline_asset_content -}}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<button
|
||||
class="country-selector__close-button button--small link"
|
||||
type="button"
|
||||
aria-label="{{ 'accessibility.close' | t }}"
|
||||
>
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</button>
|
||||
</div>
|
||||
<div id="sr-country-search-results" class="visually-hidden" aria-live="polite"></div>
|
||||
<div
|
||||
class="disclosure__list country-selector__list{% if show_currencies %} country-selector__list--with-multiple-currencies{% endif %}"
|
||||
id="{{ localPosition }}-country-results"
|
||||
>
|
||||
{% if show_popular_countries %}
|
||||
<ul
|
||||
role="list"
|
||||
class="list-unstyled popular-countries"
|
||||
aria-label="{{ 'localization.popular_countries_regions' | t }}"
|
||||
>
|
||||
{%- for country in popular_countries -%}
|
||||
<li class="disclosure__item" tabindex="-1">
|
||||
<a
|
||||
class="link link--text disclosure__link caption-large focus-inset"
|
||||
href="#"
|
||||
{% if country.iso_code == localization.country.iso_code %}
|
||||
aria-current="true"
|
||||
{% endif %}
|
||||
data-value="{{ country.iso_code }}"
|
||||
id="{{ country.name }}"
|
||||
>
|
||||
<span
|
||||
{% if country.iso_code != localization.country.iso_code %}
|
||||
class="visibility-hidden"
|
||||
{% endif %}
|
||||
>
|
||||
{{- 'icon-checkmark.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="country">{{- country.name }}</span>
|
||||
<span class="localization-form__currency motion-reduce{% unless show_currencies %} hidden{% endunless %}">
|
||||
{{ country.currency.iso_code }}
|
||||
{{ country.currency.symbol -}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{% endif %}
|
||||
<ul role="list" class="list-unstyled countries">
|
||||
{%- for country in localization.available_countries -%}
|
||||
<li class="disclosure__item" tabindex="-1">
|
||||
<a
|
||||
class="link link--text disclosure__link caption-large focus-inset"
|
||||
href="#"
|
||||
{% if country.iso_code == localization.country.iso_code %}
|
||||
aria-current="true"
|
||||
{% endif %}
|
||||
data-value="{{ country.iso_code }}"
|
||||
id="{{ country.name }}"
|
||||
>
|
||||
<span
|
||||
{% if country.iso_code != localization.country.iso_code %}
|
||||
class="visibility-hidden"
|
||||
{% endif %}
|
||||
>
|
||||
{{- 'icon-checkmark.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="country">{{- country.name }}</span>
|
||||
<span class="localization-form__currency motion-reduce{% unless show_currencies %} hidden{% endunless %}">
|
||||
{{ country.currency.iso_code }}
|
||||
{{ country.currency.symbol -}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="country-selector__overlay"></div>
|
||||
</div>
|
||||
<input type="hidden" name="country_code" value="{{ localization.country.iso_code }}">
|
||||
@@ -0,0 +1,946 @@
|
||||
{% comment %}
|
||||
Renders facets (filtering and sorting)
|
||||
|
||||
Accepts:
|
||||
- results: {Object} Collection or Search object
|
||||
- enable_filtering: {Boolean} Show filtering when true
|
||||
- enable_sorting: {Boolean} Show sorting when true
|
||||
- filter_type: {String} Type of filter
|
||||
- paginate: {Object}
|
||||
|
||||
Usage:
|
||||
{% render 'facets', results: collection, enable_filtering: true, enable_sorting: true, filter_type: 'vertical', paginate: paginate %}
|
||||
{% endcomment %}
|
||||
|
||||
{{ 'component-show-more.css' | asset_url | stylesheet_tag }}
|
||||
{{ 'component-swatch-input.css' | asset_url | stylesheet_tag }}
|
||||
{{ 'component-swatch.css' | asset_url | stylesheet_tag }}
|
||||
|
||||
{%- liquid
|
||||
assign sort_by = results.sort_by | default: results.default_sort_by
|
||||
assign total_active_values = 0
|
||||
assign default_presentation = 'text'
|
||||
if results.url
|
||||
assign results_url = results.url
|
||||
else
|
||||
assign terms = results.terms | escape
|
||||
assign results_url = '?q=' | append: terms | append: '&options%5Bprefix%5D=last&sort_by=' | append: sort_by
|
||||
endif
|
||||
-%}
|
||||
|
||||
<div
|
||||
class="facets-container{% if filter_type == 'drawer' %} facets-container-drawer{% endif %}{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--fade-in{% endif %}"
|
||||
data-collection-id="{{ results.id }}"
|
||||
data-collection-handle="{{ results.handle }}"
|
||||
data-template="{{ template.name }}"
|
||||
>
|
||||
{%- if filter_type == 'vertical' or filter_type == 'horizontal' -%}
|
||||
<facet-filters-form class="facets small-hide">
|
||||
<form
|
||||
id="FacetFiltersForm"
|
||||
class="{% if filter_type == 'horizontal' %}facets__form{% else %}facets__form-vertical{% endif %}"
|
||||
>
|
||||
{%- if results.terms -%}
|
||||
<input type="hidden" name="q" value="{{ results.terms | escape }}">
|
||||
<input name="options[prefix]" type="hidden" value="last">
|
||||
{%- endif -%}
|
||||
|
||||
{% if enable_filtering %}
|
||||
{% comment %} Heading is the first tabbable element on filter type horizontal {% endcomment %}
|
||||
<div
|
||||
id="FacetsWrapperDesktop"
|
||||
{% if filter_type == 'horizontal' %}
|
||||
class="facets__wrapper"
|
||||
{% endif %}
|
||||
>
|
||||
{%- if filter_type == 'horizontal' and results.filters != empty -%}
|
||||
<h2 class="facets__heading caption-large text-body" id="verticalTitle" tabindex="-1">
|
||||
{{ 'products.facets.filter_by_label' | t }}
|
||||
</h2>
|
||||
{%- endif -%}
|
||||
{% comment %} Pills are right below the title for filter type vertical {% endcomment %}
|
||||
{%- if filter_type == 'vertical' -%}
|
||||
<div class="active-facets active-facets-desktop">
|
||||
<div class="active-facets-vertical-filter">
|
||||
{%- unless results.filters == empty -%}
|
||||
<h2
|
||||
class="facets__heading facets__heading--vertical caption-large text-body"
|
||||
id="verticalTitle"
|
||||
tabindex="-1"
|
||||
>
|
||||
{{ 'products.facets.filter_by_label' | t }}
|
||||
</h2>
|
||||
{%- endunless -%}
|
||||
<facet-remove class="active-facets__button-wrapper">
|
||||
<a href="{{ results_url }}" class="active-facets__button-remove underlined-link">
|
||||
<span>{{ 'products.facets.clear_all' | t }}</span>
|
||||
</a>
|
||||
</facet-remove>
|
||||
</div>
|
||||
{%- for filter in results.filters -%}
|
||||
{%- for value in filter.active_values -%}
|
||||
<facet-remove>
|
||||
<a href="{{ value.url_to_remove }}" class="active-facets__button active-facets__button--light">
|
||||
<span class="active-facets__button-inner button button--tertiary">
|
||||
{{ filter.label | escape }}: {{ value.label | escape }}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close-small.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'products.facets.clear_filter' | t }}</span>
|
||||
</span>
|
||||
</a>
|
||||
</facet-remove>
|
||||
{%- endfor -%}
|
||||
{% if filter.type == 'price_range' %}
|
||||
{% assign min = filter.min_value.value %}
|
||||
{% assign max = filter.max_value.value %}
|
||||
{%- if min != null or max != null -%}
|
||||
<facet-remove>
|
||||
<a href="{{ filter.url_to_remove }}" class="active-facets__button active-facets__button--light">
|
||||
<span class="active-facets__button-inner button button--tertiary">
|
||||
{{ min | default: 0 | money }} - {{ max | default: filter.range_max | money }}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close-small.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'products.facets.clear_filter' | t }}</span>
|
||||
</span>
|
||||
</a>
|
||||
</facet-remove>
|
||||
{%- endif -%}
|
||||
{% endif %}
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
|
||||
<script src="{{ 'show-more.js' | asset_url }}" defer="defer"></script>
|
||||
{% comment %} Filters for both horizontal and vertical filter {% endcomment %}
|
||||
{%- for filter in results.filters -%}
|
||||
{% liquid
|
||||
assign total_active_values = total_active_values | plus: filter.active_values.size
|
||||
assign presentation = filter.presentation | default: default_presentation
|
||||
|
||||
if presentation == 'image'
|
||||
assign show_more_number = 12
|
||||
assign visual_layout_class = 'facets-layout facets-layout-grid facets-layout-grid--' | append: presentation
|
||||
else
|
||||
assign show_more_number = 10
|
||||
assign visual_layout_class = 'facets-layout facets-layout-list facets-layout-list--' | append: presentation
|
||||
endif
|
||||
%}
|
||||
|
||||
{% case filter.type %}
|
||||
{% when 'boolean', 'list' %}
|
||||
<details
|
||||
id="Details-{{ filter.param_name | escape }}-{{ section.id }}"
|
||||
class="{% if filter_type == 'horizontal' %}disclosure-has-popup facets__disclosure{% else %} facets__disclosure-vertical{% endif %} js-filter"
|
||||
data-index="{{ forloop.index }}"
|
||||
{% if filter_type == 'vertical' and forloop.index == 1 %}
|
||||
open
|
||||
{% endif %}
|
||||
>
|
||||
<summary
|
||||
class="facets__summary caption-large focus-offset"
|
||||
aria-label="{{ filter.label | escape }} ({{ 'products.facets.filters_selected.one' | t: count: filter.active_values.size }})"
|
||||
>
|
||||
<div>
|
||||
<span class="facets__summary-label">
|
||||
{{- filter.label | escape }}
|
||||
{%- if filter_type == 'vertical' -%}
|
||||
<span class="facets__selected{% if filter.active_values.size == 0 %} hidden{% endif %}">
|
||||
({{ filter.active_values.size }})</span
|
||||
>
|
||||
{%- endif -%}
|
||||
</span>
|
||||
{%- if filter_type == 'vertical' and filter.operator == 'AND' -%}
|
||||
<span class="facets__and-helptext">
|
||||
{{ 'products.facets.filter_and_operator_subtitle' | t }}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</div>
|
||||
</summary>
|
||||
<div
|
||||
id="Facet-{{ forloop.index }}-{{ section.id }}"
|
||||
class="parent-display {% if filter_type == 'horizontal' %}facets__display{% else %}facets__display-vertical{% endif %}"
|
||||
>
|
||||
{%- if filter_type != 'vertical' -%}
|
||||
<div class="facets__header">
|
||||
<div>
|
||||
<span class="facets__selected">
|
||||
{{- 'products.facets.filters_selected' | t: count: filter.active_values.size -}}
|
||||
</span>
|
||||
{%- if filter.operator == 'AND' -%}
|
||||
<span class="facets__and-helptext">
|
||||
{{ 'products.facets.filter_and_operator_subtitle' | t }}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<facet-remove>
|
||||
<a href="{{ filter.url_to_remove }}" class="facets__reset link underlined-link">
|
||||
{{ 'products.facets.reset' | t }}
|
||||
</a>
|
||||
</facet-remove>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<fieldset class="facets-wrap parent-wrap {% if filter_type == 'vertical' %} facets-wrap-vertical{% endif %}">
|
||||
<legend class="visually-hidden">{{ filter.label | escape }}</legend>
|
||||
{%- liquid
|
||||
assign sorted_values = filter.values
|
||||
# Keep the selected values grouped together when operator is AND
|
||||
if filter.operator == 'AND'
|
||||
assign active_filter_values = filter.values | where: 'active', true
|
||||
assign inactive_filter_values = filter.values | where: 'active', false
|
||||
assign sorted_values = active_filter_values | concat: inactive_filter_values
|
||||
endif
|
||||
-%}
|
||||
<ul
|
||||
class="{{ visual_layout_class }}{% if filter_type == 'vertical' %} facets__list--vertical{% else %} facets__list{% endif %} list-unstyled"
|
||||
role="list"
|
||||
>
|
||||
{%- for value in sorted_values -%}
|
||||
{% liquid
|
||||
assign input_id = 'Filter-' | append: filter.param_name | escape | append: '-' | append: forloop.index
|
||||
assign is_disabled = false
|
||||
if value.count == 0 and value.active == false
|
||||
assign is_disabled = true
|
||||
endif
|
||||
%}
|
||||
{%- capture label_class -%}
|
||||
facets__label facet-checkbox{% if is_disabled %} disabled{% endif %}{% if value.active %} active{% endif %}
|
||||
{%- endcapture -%}
|
||||
|
||||
{%- capture text_value -%}
|
||||
<span class="facet-checkbox__text" aria-hidden="true">
|
||||
<span class="facet-checkbox__text-label">{{- value.label | escape }}</span> ({{- value.count -}})
|
||||
</span>
|
||||
<span class="visually-hidden">
|
||||
{{- value.label | escape }} (
|
||||
{%- if value.count == 1 -%}
|
||||
{{- 'products.facets.product_count_simple.one' | t: count: value.count -}}
|
||||
{%- else -%}
|
||||
{{- 'products.facets.product_count_simple.other' | t: count: value.count -}}
|
||||
{%- endif -%}
|
||||
)
|
||||
</span>
|
||||
{%- endcapture -%}
|
||||
|
||||
<li class="list-menu__item facets__item{% if forloop.index > show_more_number and filter_type == 'vertical' %} show-more-item hidden{% endif %}">
|
||||
{%- if presentation == 'swatch' -%}
|
||||
<div class="{{ label_class }}">
|
||||
<div class="swatch-input-wrapper">
|
||||
{% render 'swatch-input',
|
||||
id: input_id,
|
||||
type: 'checkbox',
|
||||
name: value.param_name,
|
||||
value: value.value,
|
||||
product_form_id: 'FacetFiltersForm',
|
||||
swatch: value.swatch,
|
||||
checked: value.active,
|
||||
disabled: is_disabled
|
||||
%}
|
||||
</div>
|
||||
|
||||
{{ text_value }}
|
||||
</div>
|
||||
{%- else -%}
|
||||
<label for="{{ input_id }}" class="{{ label_class }}">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="{{ value.param_name }}"
|
||||
value="{{ value.value }}"
|
||||
id="{{ input_id }}"
|
||||
{% if value.active %}
|
||||
checked
|
||||
{% endif %}
|
||||
{% if is_disabled %}
|
||||
disabled
|
||||
{% endif %}
|
||||
>
|
||||
|
||||
{%- if presentation == 'image' -%}
|
||||
<div class="facets__image-wrapper">
|
||||
{%- if value.image -%}
|
||||
{{
|
||||
value.image
|
||||
| image_url: width: 300
|
||||
| image_tag: class: 'facets__image', alt: value.alt
|
||||
}}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- else -%}
|
||||
{{- 'square.svg' | inline_asset_content -}}
|
||||
|
||||
<div class="svg-wrapper">
|
||||
{{- 'icon-checkmark.svg' | inline_asset_content -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
|
||||
{{ text_value }}
|
||||
</label>
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</fieldset>
|
||||
{%- if filter.values.size > show_more_number and filter_type == 'vertical' -%}
|
||||
<show-more-button>
|
||||
<button
|
||||
class="button-show-more link underlined-link"
|
||||
id="Show-More-{{ forloop.index }}-{{ section.id }}"
|
||||
type="button"
|
||||
>
|
||||
<span class="label-show-more label-text"
|
||||
><span aria-hidden="true">+ </span>{{ 'products.facets.show_more' | t -}}
|
||||
</span>
|
||||
<span class="label-show-less label-text hidden"
|
||||
><span aria-hidden="true">- </span>{{ 'products.facets.show_less' | t -}}
|
||||
</span>
|
||||
</button>
|
||||
</show-more-button>
|
||||
{%- endif %}
|
||||
</div>
|
||||
</details>
|
||||
{% when 'price_range' %}
|
||||
<details
|
||||
id="Details-{{ filter.param_name | escape }}-{{ section.id }}"
|
||||
class="{% if filter_type == 'horizontal' %}disclosure-has-popup facets__disclosure{% else %} facets__disclosure-vertical{% endif %} js-filter"
|
||||
data-index="{{ forloop.index }}"
|
||||
{% if filter_type == 'vertical' and forloop.index == 1 %}
|
||||
open
|
||||
{% endif %}
|
||||
>
|
||||
<summary class="facets__summary caption-large focus-offset">
|
||||
<div>
|
||||
<span>{{ filter.label | escape }}</span>
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</div>
|
||||
</summary>
|
||||
<div
|
||||
id="Facet-{{ forloop.index }}-{{ section.id }}"
|
||||
class="{% if filter_type == 'horizontal' %}facets__display{% else %}facets__display-vertical{% endif %}"
|
||||
>
|
||||
<div class="{% if filter_type == 'horizontal' %}facets__header{% else %}facets__header-vertical{% endif %}">
|
||||
{%- assign max_price_amount = filter.range_max | money | strip_html | escape -%}
|
||||
<span class="facets__selected">
|
||||
{{- 'products.facets.max_price' | t: price: max_price_amount -}}
|
||||
</span>
|
||||
{%- if filter_type != 'vertical' -%}
|
||||
<facet-remove>
|
||||
<a href="{{ filter.url_to_remove }}" class="facets__reset link underlined-link">
|
||||
{{ 'products.facets.reset' | t }}
|
||||
</a>
|
||||
</facet-remove>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<price-range class="facets__price">
|
||||
{% render 'price-facet', filter: filter, id_prefix: 'Filter-', filter_type: filter_type %}
|
||||
</price-range>
|
||||
</div>
|
||||
</details>
|
||||
{% endcase %}
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
{% comment %} Pills after filtes on filter type horizontal {% endcomment %}
|
||||
{%- if filter_type == 'horizontal' -%}
|
||||
<div class="active-facets active-facets-desktop">
|
||||
{%- for filter in results.filters -%}
|
||||
{%- for value in filter.active_values -%}
|
||||
<facet-remove>
|
||||
<a href="{{ value.url_to_remove }}" class="active-facets__button active-facets__button--light">
|
||||
<span class="active-facets__button-inner button button--tertiary">
|
||||
{{ filter.label | escape }}: {{ value.label | escape }}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close-small.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'products.facets.clear_filter' | t }}</span>
|
||||
</span>
|
||||
</a>
|
||||
</facet-remove>
|
||||
{%- endfor -%}
|
||||
{% if filter.type == 'price_range' %}
|
||||
{% assign min = filter.min_value.value %}
|
||||
{% assign max = filter.max_value.value %}
|
||||
{%- if min != null or max != null -%}
|
||||
<facet-remove>
|
||||
<a href="{{ filter.url_to_remove }}" class="active-facets__button active-facets__button--light">
|
||||
<span class="active-facets__button-inner button button--tertiary">
|
||||
{{ min | default: 0 | money }} - {{ max | default: filter.range_max | money }}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close-small.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'products.facets.clear_filter' | t }}</span>
|
||||
</span>
|
||||
</a>
|
||||
</facet-remove>
|
||||
{%- endif -%}
|
||||
{% endif %}
|
||||
{%- endfor -%}
|
||||
<facet-remove class="active-facets__button-wrapper">
|
||||
<a href="{{ results_url }}" class="active-facets__button-remove underlined-link">
|
||||
<span>{{ 'products.facets.clear_all' | t }}</span>
|
||||
</a>
|
||||
</facet-remove>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{% endif %}
|
||||
|
||||
{% if results.current_vendor or results.current_type %}
|
||||
<input type="hidden" name="q" value="{{ results.current_vendor }}{{ results.current_type }}">
|
||||
{% endif %}
|
||||
|
||||
{%- if filter_type == 'horizontal' -%}
|
||||
{% comment %} Sorting and product count are the last elements when filter type is horizontal {% endcomment %}
|
||||
{%- if enable_sorting -%}
|
||||
<div class="facet-filters sorting caption">
|
||||
<div class="facet-filters__field">
|
||||
<h2 class="facet-filters__label caption-large text-body">
|
||||
<label for="SortBy">{{ 'products.facets.sort_by_label' | t }}</label>
|
||||
</h2>
|
||||
<div class="select">
|
||||
{%- assign sort_by = results.sort_by | default: results.default_sort_by -%}
|
||||
<select
|
||||
name="sort_by"
|
||||
class="facet-filters__sort select__select caption-large"
|
||||
id="SortBy"
|
||||
aria-describedby="a11y-refresh-page-message"
|
||||
>
|
||||
{%- for option in results.sort_options -%}
|
||||
<option
|
||||
value="{{ option.value | escape }}"
|
||||
{% if option.value == sort_by %}
|
||||
selected="selected"
|
||||
{% endif %}
|
||||
>
|
||||
{{ option.name | escape }}
|
||||
</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<div class="product-count light" role="status">
|
||||
<h2 class="product-count__text text-body">
|
||||
<span id="ProductCountDesktop">
|
||||
{%- if results.results_count -%}
|
||||
{{ 'templates.search.results_with_count' | t: terms: results.terms, count: results.results_count }}
|
||||
{%- elsif results.products_count == results.all_products_count -%}
|
||||
{{ 'products.facets.product_count_simple' | t: count: results.products_count }}
|
||||
{%- else -%}
|
||||
{{
|
||||
'products.facets.product_count'
|
||||
| t: product_count: results.products_count, count: results.all_products_count
|
||||
}}
|
||||
{%- endif -%}
|
||||
</span>
|
||||
</h2>
|
||||
{%- render 'loading-spinner' -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</form>
|
||||
</facet-filters-form>
|
||||
{%- endif -%}
|
||||
{% comment %} Drawer and mobile filter {% endcomment %}
|
||||
<menu-drawer
|
||||
class="mobile-facets__wrapper{% if filter_type == 'horizontal' or filter_type == 'vertical' %} medium-hide large-up-hide{% endif %}"
|
||||
data-breakpoint="mobile"
|
||||
>
|
||||
<details class="mobile-facets__disclosure disclosure-has-popup">
|
||||
<summary class="mobile-facets__open-wrapper focus-offset">
|
||||
<span class="mobile-facets__open{% if filter_type == 'drawer' and enable_filtering == false %} medium-hide large-up-hide{% endif %}">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-filter.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="mobile-facets__open-label button-label medium-hide large-up-hide">
|
||||
{%- if enable_filtering and enable_sorting -%}
|
||||
{{ 'products.facets.filter_and_sort' | t }}
|
||||
{%- elsif enable_filtering -%}
|
||||
{{ 'products.facets.filter_button' | t }}
|
||||
{%- elsif enable_sorting -%}
|
||||
{{ 'products.facets.sort_button' | t }}
|
||||
{%- endif -%}
|
||||
</span>
|
||||
<span class="mobile-facets__open-label button-label small-hide">
|
||||
{%- if enable_filtering -%}
|
||||
{{ 'products.facets.filter_button' | t }}
|
||||
{%- endif -%}
|
||||
</span>
|
||||
</span>
|
||||
<span tabindex="0" class="mobile-facets__close">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</span>
|
||||
</summary>
|
||||
<facet-filters-form>
|
||||
<form id="FacetFiltersFormMobile" class="mobile-facets">
|
||||
<div class="mobile-facets__inner gradient">
|
||||
<div class="mobile-facets__header">
|
||||
<div class="mobile-facets__header-inner">
|
||||
<h2 class="mobile-facets__heading medium-hide large-up-hide">
|
||||
{%- if enable_filtering and enable_sorting -%}
|
||||
{{ 'products.facets.filter_and_sort' | t }}
|
||||
{%- elsif enable_filtering -%}
|
||||
{{ 'products.facets.filter_button' | t }}
|
||||
{%- elsif enable_sorting -%}
|
||||
{{ 'products.facets.sort_button' | t }}
|
||||
{%- endif -%}
|
||||
</h2>
|
||||
<h2 class="mobile-facets__heading small-hide">
|
||||
{%- if enable_filtering -%}
|
||||
{{ 'products.facets.filter_button' | t }}
|
||||
{%- endif -%}
|
||||
</h2>
|
||||
<p class="mobile-facets__count">
|
||||
{%- if results.results_count -%}
|
||||
{{ 'templates.search.results_with_count' | t: terms: results.terms, count: results.results_count }}
|
||||
{%- elsif results.products_count == results.all_products_count -%}
|
||||
{{ 'products.facets.product_count_simple' | t: count: results.products_count }}
|
||||
{%- else -%}
|
||||
{{
|
||||
'products.facets.product_count'
|
||||
| t: product_count: results.products_count, count: results.all_products_count
|
||||
}}
|
||||
{%- endif -%}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
id="FacetsWrapperMobile"
|
||||
class="mobile-facets__main has-submenu gradient"
|
||||
>
|
||||
{%- if enable_filtering -%}
|
||||
{%- for filter in results.filters -%}
|
||||
{% liquid
|
||||
assign presentation = filter.presentation | default: default_presentation
|
||||
if presentation == 'image'
|
||||
assign visual_layout_class = 'facets-layout facets-layout-grid facets-layout-grid--' | append: presentation
|
||||
else
|
||||
assign visual_layout_class = 'facets-layout facets-layout-list facets-layout-list--' | append: presentation
|
||||
endif
|
||||
%}
|
||||
|
||||
{% case filter.type %}
|
||||
{% when 'boolean', 'list' %}
|
||||
<details
|
||||
id="Details-Mobile-{{ filter.param_name | escape }}-{{ section.id }}"
|
||||
class="mobile-facets__details js-filter"
|
||||
data-index="mobile-{{ forloop.index }}"
|
||||
>
|
||||
<summary class="mobile-facets__summary focus-inset">
|
||||
<div>
|
||||
<span>{{ filter.label | escape }}</span>
|
||||
<span class="mobile-facets__arrow">
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</div>
|
||||
</summary>
|
||||
<div
|
||||
id="FacetMobile-{{ forloop.index }}-{{ section.id }}"
|
||||
class="mobile-facets__submenu gradient"
|
||||
>
|
||||
<button
|
||||
class="mobile-facets__close-button link link--text focus-inset"
|
||||
aria-expanded="true"
|
||||
type="button"
|
||||
>
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
<span>{{ filter.label | escape }}</span>
|
||||
{%- if filter.operator == 'AND' -%}
|
||||
<span class="facets__and-helptext">
|
||||
{{ 'products.facets.filter_and_operator_subtitle' | t }}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</button>
|
||||
<ul class="{{ visual_layout_class }} mobile-facets__list list-unstyled" role="list">
|
||||
{%- liquid
|
||||
assign sorted_values = filter.values
|
||||
# Keep the selected values grouped together when operator is AND
|
||||
if filter.operator == 'AND'
|
||||
assign active_filter_values = filter.values | where: 'active', true
|
||||
assign inactive_filter_values = filter.values | where: 'active', false
|
||||
assign sorted_values = active_filter_values | concat: inactive_filter_values
|
||||
endif
|
||||
-%}
|
||||
{%- for value in sorted_values -%}
|
||||
{% liquid
|
||||
assign input_id = 'Filter-' | append: filter.param_name | escape | append: '-mobile-' | append: forloop.index
|
||||
assign is_disabled = false
|
||||
if value.count == 0 and value.active == false
|
||||
assign is_disabled = true
|
||||
endif
|
||||
%}
|
||||
|
||||
{%- capture label_class -%}
|
||||
facets__label mobile-facets__label{% if is_disabled %} disabled{% endif %}{% if value.active %} active{% endif %}
|
||||
{%- endcapture -%}
|
||||
|
||||
{%- capture text_value -%}
|
||||
<span class="facet-checkbox__text" aria-hidden="true">
|
||||
<span class="facet-checkbox__text-label">{{- value.label | escape }}</span> ({{- value.count -}})
|
||||
</span>
|
||||
<span class="visually-hidden">
|
||||
{{- value.label | escape }} (
|
||||
{%- if value.count == '1' -%}
|
||||
{{- 'products.facets.product_count_simple.one' | t: count: value.count -}}
|
||||
{%- else -%}
|
||||
{{- 'products.facets.product_count_simple.other' | t: count: value.count -}}
|
||||
{%- endif -%}
|
||||
)
|
||||
</span>
|
||||
{%- endcapture -%}
|
||||
|
||||
<li class="mobile-facets__item list-menu__item">
|
||||
{% if presentation == 'swatch' %}
|
||||
<div class="{{ label_class }}">
|
||||
<div class="swatch-input-wrapper">
|
||||
{% render 'swatch-input',
|
||||
id: input_id,
|
||||
type: 'checkbox',
|
||||
name: value.param_name,
|
||||
value: value.value,
|
||||
product_form_id: 'FacetFiltersFormMobile',
|
||||
swatch: value.swatch,
|
||||
checked: value.active,
|
||||
disabled: is_disabled
|
||||
%}
|
||||
</div>
|
||||
|
||||
{{ text_value }}
|
||||
</div>
|
||||
{% else %}
|
||||
<label for="{{ input_id }}" class="{{ label_class }}">
|
||||
<input
|
||||
class="mobile-facets__checkbox"
|
||||
type="checkbox"
|
||||
name="{{ value.param_name }}"
|
||||
value="{{ value.value }}"
|
||||
id="{{ input_id }}"
|
||||
{% if value.active %}
|
||||
checked
|
||||
{% endif %}
|
||||
{% if is_disabled %}
|
||||
disabled
|
||||
{% endif %}
|
||||
>
|
||||
|
||||
{%- if presentation == 'image' -%}
|
||||
<div class="facets__image-wrapper">
|
||||
{%- if value.image -%}
|
||||
{{
|
||||
value.image
|
||||
| image_url: width: 300
|
||||
| image_tag: class: 'facets__image', alt: value.alt
|
||||
}}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- else -%}
|
||||
<span class="mobile-facets__highlight"></span>
|
||||
{{- 'square.svg' | inline_asset_content -}}
|
||||
{{- 'icon-checkmark.svg' | inline_asset_content -}}
|
||||
{%- endif %}
|
||||
|
||||
{{ text_value }}
|
||||
</label>
|
||||
{% endif %}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
|
||||
<div class="mobile-facets__footer gradient">
|
||||
<facet-remove class="mobile-facets__clear-wrapper">
|
||||
<a href="{{ filter.url_to_remove }}" class="mobile-facets__clear underlined-link">
|
||||
{{- 'products.facets.clear' | t -}}
|
||||
</a>
|
||||
</facet-remove>
|
||||
<button
|
||||
type="button"
|
||||
class="button button--primary"
|
||||
onclick="this.closest('.mobile-facets__wrapper').querySelector('summary').click()"
|
||||
>
|
||||
{{ 'products.facets.apply' | t }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
{% when 'price_range' %}
|
||||
<details
|
||||
id="Details-Mobile-{{ filter.param_name | escape }}-{{ section.id }}"
|
||||
class="mobile-facets__details js-filter"
|
||||
data-index="mobile-{{ forloop.index }}"
|
||||
>
|
||||
<summary class="mobile-facets__summary focus-inset">
|
||||
<div>
|
||||
<span>{{ filter.label | escape }}</span>
|
||||
<span class="mobile-facets__arrow">
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</div>
|
||||
</summary>
|
||||
<div
|
||||
id="FacetMobile-{{ forloop.index }}-{{ section.id }}"
|
||||
class="mobile-facets__submenu gradient"
|
||||
>
|
||||
<button
|
||||
class="mobile-facets__close-button link link--text focus-inset"
|
||||
aria-expanded="true"
|
||||
type="button"
|
||||
>
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
{{ filter.label | escape }}
|
||||
</button>
|
||||
|
||||
{%- assign max_price_amount = filter.range_max | money | strip_html | escape -%}
|
||||
<p class="mobile-facets__info">
|
||||
{{ 'products.facets.max_price' | t: price: max_price_amount }}
|
||||
</p>
|
||||
|
||||
<price-range class="facets__price">
|
||||
{% render 'price-facet', filter: filter, id_prefix: 'Mobile-Filter-' %}
|
||||
</price-range>
|
||||
<div class="mobile-facets__footer">
|
||||
<facet-remove class="mobile-facets__clear-wrapper">
|
||||
<a href="{{ filter.url_to_remove }}" class="mobile-facets__clear underlined-link">
|
||||
{{- 'products.facets.clear' | t -}}
|
||||
</a>
|
||||
</facet-remove>
|
||||
<button
|
||||
type="button"
|
||||
class="button button--primary"
|
||||
onclick="this.closest('.mobile-facets__wrapper').querySelector('summary').click()"
|
||||
>
|
||||
{{ 'products.facets.apply' | t }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
{% endcase %}
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
|
||||
{%- if enable_sorting -%}
|
||||
<div
|
||||
id="Details-Mobile-SortBy-{{ section.id }}"
|
||||
class="mobile-facets__details js-filter{% if filter_type == 'drawer' %} medium-hide large-up-hide{% endif %}"
|
||||
data-index="mobile-{{ forloop.index }}"
|
||||
>
|
||||
<div class="mobile-facets__summary">
|
||||
<div class="mobile-facets__sort">
|
||||
<label for="SortBy-mobile">{{ 'products.facets.sort_by_label' | t }}</label>
|
||||
<div class="select">
|
||||
<select
|
||||
name="sort_by"
|
||||
class="select__select"
|
||||
id="SortBy-mobile"
|
||||
aria-describedby="a11y-refresh-page-message"
|
||||
>
|
||||
{%- for option in results.sort_options -%}
|
||||
<option
|
||||
value="{{ option.value | escape }}"
|
||||
{% if option.value == sort_by %}
|
||||
selected="selected"
|
||||
{% endif %}
|
||||
>
|
||||
{{ option.name | escape }}
|
||||
</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
|
||||
<div class="mobile-facets__footer">
|
||||
<facet-remove class="mobile-facets__clear-wrapper">
|
||||
<a href="{{ results_url }}" class="mobile-facets__clear underlined-link">
|
||||
{{- 'products.facets.clear_all' | t -}}
|
||||
</a>
|
||||
</facet-remove>
|
||||
<button
|
||||
type="button"
|
||||
class="button button--primary"
|
||||
onclick="this.closest('.mobile-facets__wrapper').querySelector('summary').click()"
|
||||
>
|
||||
{{ 'products.facets.apply' | t }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if results.current_vendor or results.current_type %}
|
||||
<input type="hidden" name="q" value="{{ results.current_vendor }}{{ results.current_type }}">
|
||||
{% endif %}
|
||||
|
||||
{%- if results.terms -%}
|
||||
<input type="hidden" name="q" value="{{ results.terms | escape }}">
|
||||
<input name="options[prefix]" type="hidden" value="last">
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</form>
|
||||
</facet-filters-form>
|
||||
</details>
|
||||
</menu-drawer>
|
||||
|
||||
<div class="active-facets active-facets-mobile medium-hide large-up-hide">
|
||||
{%- for filter in results.filters -%}
|
||||
{%- for value in filter.active_values -%}
|
||||
<facet-remove>
|
||||
<a href="{{ value.url_to_remove }}" class="active-facets__button active-facets__button--light">
|
||||
<span class="active-facets__button-inner button button--tertiary">
|
||||
{{ filter.label | escape }}: {{ value.label | escape }}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close-small.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'products.facets.clear_filter' | t }}</span>
|
||||
</span>
|
||||
</a>
|
||||
</facet-remove>
|
||||
{%- endfor -%}
|
||||
|
||||
{%- if filter.type == 'price_range' -%}
|
||||
{% assign min = filter.min_value.value %}
|
||||
{% assign max = filter.max_value.value %}
|
||||
{%- if min != null or max != null -%}
|
||||
<facet-remove>
|
||||
<a href="{{ filter.url_to_remove }}" class="active-facets__button active-facets__button--light">
|
||||
<span class="active-facets__button-inner button button--tertiary">
|
||||
{{ min | default: 0 | money }} - {{ max | default: filter.range_max | money }}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close-small.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'products.facets.clear_filter' | t }}</span>
|
||||
</span>
|
||||
</a>
|
||||
</facet-remove>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
<facet-remove class="active-facets__button-wrapper">
|
||||
<a href="{{ results_url }}" class="active-facets__button-remove underlined-link">
|
||||
<span>{{ 'products.facets.clear_all' | t }}</span>
|
||||
</a>
|
||||
</facet-remove>
|
||||
</div>
|
||||
{% comment %} Sort, product count and filter pills at the end when filter is type of Drawer for the correct tabbing order {% endcomment %}
|
||||
{%- if enable_sorting and filter_type == 'drawer' -%}
|
||||
<facet-filters-form class="facets small-hide">
|
||||
<form id="FacetSortDrawerForm" class="facets__form">
|
||||
<div class="facet-filters sorting caption small-hide">
|
||||
<div class="facet-filters__field">
|
||||
<h2 class="facet-filters__label caption-large text-body">
|
||||
<label for="SortBy">{{ 'products.facets.sort_by_label' | t }}</label>
|
||||
</h2>
|
||||
<div class="select">
|
||||
{%- assign sort_by = results.sort_by | default: results.default_sort_by -%}
|
||||
<select
|
||||
name="sort_by"
|
||||
class="facet-filters__sort select__select caption-large"
|
||||
id="SortBy"
|
||||
aria-describedby="a11y-refresh-page-message"
|
||||
>
|
||||
{%- for option in results.sort_options -%}
|
||||
<option
|
||||
value="{{ option.value | escape }}"
|
||||
{% if option.value == sort_by %}
|
||||
selected="selected"
|
||||
{% endif %}
|
||||
>
|
||||
{{ option.name | escape }}
|
||||
</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if results.current_vendor or results.current_type %}
|
||||
<input type="hidden" name="q" value="{{ results.current_vendor }}{{ results.current_type }}">
|
||||
{% endif %}
|
||||
|
||||
{%- if results.terms -%}
|
||||
<input type="hidden" name="q" value="{{ results.terms | escape }}">
|
||||
<input name="options[prefix]" type="hidden" value="last">
|
||||
{%- endif -%}
|
||||
</form>
|
||||
</facet-filters-form>
|
||||
{%- endif -%}
|
||||
<div
|
||||
class="product-count light{% if filter_type == 'vertical' or filter_type == 'horizontal' %} medium-hide large-up-hide{% endif %}"
|
||||
role="status"
|
||||
>
|
||||
<h2 class="product-count__text text-body">
|
||||
<span
|
||||
id="ProductCount"
|
||||
data-product-count="{{ results.products_count | default: results.results_count }}"
|
||||
data-total-count="{{ results.all_products_count | default: results.products_count | default: results.results_count }}"
|
||||
>
|
||||
{%- if results.results_count -%}
|
||||
{{ 'templates.search.results_with_count' | t: terms: results.terms, count: results.results_count }}
|
||||
{%- elsif results.products_count == results.all_products_count -%}
|
||||
{{ 'products.facets.product_count_simple' | t: count: results.products_count }}
|
||||
{%- else -%}
|
||||
{{
|
||||
'products.facets.product_count'
|
||||
| t: product_count: results.products_count, count: results.all_products_count
|
||||
}}
|
||||
{%- endif -%}
|
||||
</span>
|
||||
</h2>
|
||||
{%- render 'loading-spinner' -%}
|
||||
</div>
|
||||
{%- if filter_type == 'drawer' -%}
|
||||
<facet-filters-form class="facets facets-pill small-hide">
|
||||
<form id="FacetFiltersPillsForm" class="facets__form">
|
||||
<div class="active-facets active-facets-desktop">
|
||||
{%- for filter in results.filters -%}
|
||||
{%- for value in filter.active_values -%}
|
||||
<facet-remove>
|
||||
<a href="{{ value.url_to_remove }}" class="active-facets__button active-facets__button--light">
|
||||
<span class="active-facets__button-inner button button--tertiary">
|
||||
{{ filter.label | escape }}: {{ value.label | escape }}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close-small.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'products.facets.clear_filter' | t }}</span>
|
||||
</span>
|
||||
</a>
|
||||
</facet-remove>
|
||||
{%- endfor -%}
|
||||
|
||||
{%- if filter.type == 'price_range' -%}
|
||||
{% assign min = filter.min_value.value %}
|
||||
{% assign max = filter.max_value.value %}
|
||||
{%- if min != null or max != null -%}
|
||||
<facet-remove>
|
||||
<a href="{{ filter.url_to_remove }}" class="active-facets__button active-facets__button--light">
|
||||
<span class="active-facets__button-inner button button--tertiary">
|
||||
{{ min | default: 0 | money }} - {{ max | default: filter.range_max | money }}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close-small.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'products.facets.clear_filter' | t }}</span>
|
||||
</span>
|
||||
</a>
|
||||
</facet-remove>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
<facet-remove class="active-facets__button-wrapper">
|
||||
<a href="{{ results_url }}" class="active-facets__button-remove underlined-link">
|
||||
<span>{{ 'products.facets.clear_all' | t }}</span>
|
||||
</a>
|
||||
</facet-remove>
|
||||
</div>
|
||||
</form>
|
||||
</facet-filters-form>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
@@ -0,0 +1,222 @@
|
||||
{% comment %}
|
||||
Renders gift card recipient form.
|
||||
Accepts:
|
||||
- product: {Object} product object.
|
||||
- form: {Object} the product form object.
|
||||
- section: {Object} section to which this snippet belongs.
|
||||
|
||||
Usage:
|
||||
{% render 'gift-card-recipient-form', product: product, form: form, section: section %}
|
||||
{% endcomment %}
|
||||
|
||||
<div class="customer">
|
||||
{%- assign gift_card_recipient_control_flag = 'properties[__shopify_send_gift_card_to_recipient]' -%}
|
||||
<script src="{{ 'recipient-form.js' | asset_url }}" defer="defer"></script>
|
||||
<recipient-form
|
||||
class="recipient-form"
|
||||
data-section-id="{{ section.id }}"
|
||||
data-product-variant-id="{{ product.selected_or_first_available_variant.id }}"
|
||||
>
|
||||
<input
|
||||
id="Recipient-checkbox-{{ section.id }}"
|
||||
type="checkbox"
|
||||
name="{{ gift_card_recipient_control_flag }}"
|
||||
disabled
|
||||
>
|
||||
<label class="recipient-checkbox" for="Recipient-checkbox-{{ section.id }}">
|
||||
{{ 'square.svg' | inline_asset_content }}
|
||||
{{- 'icon-checkmark.svg' | inline_asset_content -}}
|
||||
<span>{{ 'recipient.form.checkbox' | t }}</span>
|
||||
</label>
|
||||
<div
|
||||
class="product-form__recipient-error-message-wrapper"
|
||||
role="alert"
|
||||
{% unless form.errors %}
|
||||
hidden
|
||||
{% endunless %}
|
||||
>
|
||||
<h2 class="form__message" tabindex="-1" autofocus>
|
||||
{{- 'icon-error.svg' | inline_asset_content -}}
|
||||
<span class="error-message">{{ 'templates.contact.form.error_heading' | t }}</span>
|
||||
</h2>
|
||||
|
||||
<ul>
|
||||
{%- if form.errors -%}
|
||||
{%- for field in form.errors -%}
|
||||
<li>
|
||||
{%- if field == 'form' -%}
|
||||
{{ form.errors.messages[field] }}
|
||||
{%- else -%}
|
||||
<a href="#Recipient-{{ field }}-{{ section.id }}">
|
||||
{{ form.errors.messages[field] }}
|
||||
</a>
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
</ul>
|
||||
</div>
|
||||
<p
|
||||
id="Recipient-fields-live-region-{{ section.id }}"
|
||||
class="visually-hidden"
|
||||
role="status"
|
||||
></p>
|
||||
<div class="recipient-fields">
|
||||
<hr>
|
||||
<div class="recipient-fields__field">
|
||||
<div class="field">
|
||||
<input
|
||||
class="field__input"
|
||||
id="Recipient-email-{{ section.id }}"
|
||||
type="email"
|
||||
placeholder="{{ 'recipient.form.email' | t }}"
|
||||
name="properties[Recipient email]"
|
||||
value="{{ form.email }}"
|
||||
{% if form.errors contains 'email' %}
|
||||
aria-invalid="true"
|
||||
aria-describedby="RecipientForm-email-error-{{ section.id }}"
|
||||
{% endif %}
|
||||
>
|
||||
<label class="field__label" for="Recipient-email-{{ section.id }}">
|
||||
<span class="recipient-email-label required">{{ 'recipient.form.email_label' | t }}</span>
|
||||
<span class="recipient-email-label optional">
|
||||
{{- 'recipient.form.email_label_optional_for_no_js_behavior' | t -}}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="RecipientForm-email-error-{{ section.id }}"
|
||||
class="form__message{% unless form.errors contains 'email' %} hidden{% endunless %}"
|
||||
>
|
||||
{{- 'icon-error.svg' | inline_asset_content -}}
|
||||
<span class="error-message">
|
||||
{%- if form.errors contains 'email' -%}
|
||||
{{ form.errors.messages.email }}.
|
||||
{%- endif -%}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="recipient-fields__field">
|
||||
<div class="field">
|
||||
<input
|
||||
class="field__input"
|
||||
autocomplete="name"
|
||||
type="text"
|
||||
id="Recipient-name-{{ section.id }}"
|
||||
name="properties[Recipient name]"
|
||||
placeholder="{{ 'recipient.form.name' | t }}"
|
||||
value="{{ form.name }}"
|
||||
{% if form.errors contains 'name' %}
|
||||
aria-invalid="true"
|
||||
aria-describedby="RecipientForm-name-error-{{ section.id }}"
|
||||
{% endif %}
|
||||
>
|
||||
<label class="field__label" for="Recipient-name-{{ section.id }}">
|
||||
{{- 'recipient.form.name_label' | t -}}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="RecipientForm-name-error-{{ section.id }}"
|
||||
class="form__message{% unless form.errors contains 'name' %} hidden{% endunless %}"
|
||||
>
|
||||
{{- 'icon-error.svg' | inline_asset_content -}}
|
||||
<span class="error-message">
|
||||
{%- if form.errors contains 'name' -%}
|
||||
{{ form.errors.messages.name }}.
|
||||
{%- endif -%}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="recipient-fields__field">
|
||||
{%- assign max_chars_message = 200 -%}
|
||||
{%- assign max_chars_message_rendered = 'recipient.form.max_characters' | t: max_chars: max_chars_message -%}
|
||||
{%- assign message_label_rendered = 'recipient.form.message_label' | t -%}
|
||||
<div class="field">
|
||||
<textarea
|
||||
rows="10"
|
||||
id="Recipient-message-{{ section.id }}"
|
||||
class="text-area field__input"
|
||||
name="properties[Message]"
|
||||
maxlength="{{ max_chars_message }}"
|
||||
placeholder="{{ 'recipient.form.message' | t }}"
|
||||
aria-label="{{ message_label_rendered }} {{ max_chars_message_rendered }}"
|
||||
{% if form.errors contains 'message' %}
|
||||
aria-invalid="true"
|
||||
aria-describedby="RecipientForm-message-error-{{ section.id }}"
|
||||
{% endif %}
|
||||
>{{ form.message }}</textarea>
|
||||
<label class="form__label field__label" for="Recipient-message-{{ section.id }}">
|
||||
{{ message_label_rendered }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label class="form__label recipient-form-field-label recipient-form-field-label--space-between">
|
||||
<span>{{ max_chars_message_rendered }}</span>
|
||||
</label>
|
||||
|
||||
<div
|
||||
id="RecipientForm-message-error-{{ section.id }}"
|
||||
class="form__message{% unless form.errors contains 'message' %} hidden{% endunless %}"
|
||||
>
|
||||
{{- 'icon-error.svg' | inline_asset_content -}}
|
||||
<span class="error-message">
|
||||
{%- if form.errors contains 'message' -%}
|
||||
{{ form.errors.messages.message }}.
|
||||
{%- endif -%}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="recipient-fields__field">
|
||||
<div class="field">
|
||||
<input
|
||||
class="field__input text-body"
|
||||
autocomplete="send_on"
|
||||
type="date"
|
||||
id="Recipient-send-on-{{ section.id }}"
|
||||
name="properties[Send on]"
|
||||
placeholder="{{ 'recipient.form.send_on' | t }}"
|
||||
pattern="\d{4}-\d{2}-\d{2}"
|
||||
value="{{ form.send_on }}"
|
||||
{% if form.errors contains 'send_on' %}
|
||||
aria-invalid="true"
|
||||
aria-describedby="RecipientForm-send_on-error-{{ section.id }}"
|
||||
{% endif %}
|
||||
>
|
||||
<label class="form__label field__label" for="Recipient-send-on-{{ section.id }}">
|
||||
{{ 'recipient.form.send_on_label' | t }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="RecipientForm-send_on-error-{{ section.id }}"
|
||||
class="form__message{% unless form.errors contains 'send_on' %} hidden{% endunless %}"
|
||||
>
|
||||
{{- 'icon-error.svg' | inline_asset_content -}}
|
||||
<span class="error-message">
|
||||
{%- if form.errors contains 'send_on' -%}
|
||||
{{ form.errors.messages.send_on }}.
|
||||
{%- endif -%}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
type="hidden"
|
||||
name="{{ gift_card_recipient_control_flag }}"
|
||||
value="if_present"
|
||||
id="Recipient-control-{{ section.id }}"
|
||||
>
|
||||
<input
|
||||
type="hidden"
|
||||
name="properties[__shopify_offset]"
|
||||
value=""
|
||||
id="Recipient-timezone-offset-{{ section.id }}"
|
||||
disabled
|
||||
>
|
||||
</recipient-form>
|
||||
</div>
|
||||
@@ -0,0 +1,295 @@
|
||||
{% comment %}
|
||||
Renders a header drawer menu for mobile and desktop.
|
||||
|
||||
Usage:
|
||||
{% render 'header-drawer' %}
|
||||
{% endcomment %}
|
||||
|
||||
<header-drawer data-breakpoint="{% if section.settings.menu_type_desktop == 'drawer' %}desktop{% else %}tablet{% endif %}">
|
||||
<details id="Details-menu-drawer-container" class="menu-drawer-container">
|
||||
<summary
|
||||
class="header__icon header__icon--menu header__icon--summary link focus-inset"
|
||||
aria-label="{{ 'sections.header.menu' | t }}"
|
||||
>
|
||||
<span>
|
||||
{{- 'icon-hamburger.svg' | inline_asset_content -}}
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</summary>
|
||||
<div id="menu-drawer" class="gradient menu-drawer motion-reduce color-{{ section.settings.menu_color_scheme }}">
|
||||
<div class="menu-drawer__inner-container">
|
||||
<div class="menu-drawer__navigation-container">
|
||||
<nav class="menu-drawer__navigation">
|
||||
<ul class="menu-drawer__menu has-submenu list-menu" role="list">
|
||||
{%- for link in section.settings.menu.links -%}
|
||||
<li>
|
||||
{%- if link.links != blank -%}
|
||||
<details id="Details-menu-drawer-menu-item-{{ forloop.index }}">
|
||||
<summary
|
||||
id="HeaderDrawer-{{ link.handle }}"
|
||||
class="menu-drawer__menu-item list-menu__item link link--text focus-inset{% if link.child_active %} menu-drawer__menu-item--active{% endif %}"
|
||||
>
|
||||
{{ link.title | escape }}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</summary>
|
||||
<div
|
||||
id="link-{{ link.handle | escape }}"
|
||||
class="menu-drawer__submenu has-submenu gradient motion-reduce"
|
||||
tabindex="-1"
|
||||
>
|
||||
<div class="menu-drawer__inner-submenu">
|
||||
<button class="menu-drawer__close-button link link--text focus-inset" aria-expanded="true">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{{ link.title | escape }}
|
||||
</button>
|
||||
<ul class="menu-drawer__menu list-menu" role="list" tabindex="-1">
|
||||
{%- for childlink in link.links -%}
|
||||
<li>
|
||||
{%- if childlink.links == blank -%}
|
||||
<a
|
||||
id="HeaderDrawer-{{ link.handle }}-{{ childlink.handle }}"
|
||||
href="{{ childlink.url }}"
|
||||
class="menu-drawer__menu-item link link--text list-menu__item focus-inset{% if childlink.current %} menu-drawer__menu-item--active{% endif %}"
|
||||
{% if childlink.current %}
|
||||
aria-current="page"
|
||||
{% endif %}
|
||||
>
|
||||
{{ childlink.title | escape }}
|
||||
</a>
|
||||
{%- else -%}
|
||||
<details id="Details-menu-drawer-{{ link.handle }}-{{ childlink.handle }}">
|
||||
<summary
|
||||
id="HeaderDrawer-{{ link.handle }}-{{ childlink.handle }}"
|
||||
class="menu-drawer__menu-item link link--text list-menu__item focus-inset"
|
||||
>
|
||||
{{ childlink.title | escape }}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</summary>
|
||||
<div
|
||||
id="childlink-{{ childlink.handle | escape }}"
|
||||
class="menu-drawer__submenu has-submenu gradient motion-reduce"
|
||||
>
|
||||
<button
|
||||
class="menu-drawer__close-button link link--text focus-inset"
|
||||
aria-expanded="true"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-arrow.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{{ childlink.title | escape }}
|
||||
</button>
|
||||
<ul
|
||||
class="menu-drawer__menu list-menu"
|
||||
role="list"
|
||||
tabindex="-1"
|
||||
>
|
||||
{%- for grandchildlink in childlink.links -%}
|
||||
<li>
|
||||
<a
|
||||
id="HeaderDrawer-{{ link.handle }}-{{ childlink.handle }}-{{ grandchildlink.handle }}"
|
||||
href="{{ grandchildlink.url }}"
|
||||
class="menu-drawer__menu-item link link--text list-menu__item focus-inset{% if grandchildlink.current %} menu-drawer__menu-item--active{% endif %}"
|
||||
{% if grandchildlink.current %}
|
||||
aria-current="page"
|
||||
{% endif %}
|
||||
>
|
||||
{{ grandchildlink.title | escape }}
|
||||
</a>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</div>
|
||||
</details>
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
{%- else -%}
|
||||
<a
|
||||
id="HeaderDrawer-{{ link.handle }}"
|
||||
href="{{ link.url }}"
|
||||
class="menu-drawer__menu-item list-menu__item link link--text focus-inset{% if link.current %} menu-drawer__menu-item--active{% endif %}"
|
||||
{% if link.current %}
|
||||
aria-current="page"
|
||||
{% endif %}
|
||||
>
|
||||
{{ link.title | escape }}
|
||||
</a>
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="menu-drawer__utility-links">
|
||||
{%- if shop.customer_accounts_enabled -%}
|
||||
<a
|
||||
href="{%- if customer -%}{{ routes.account_url }}{%- else -%}{{ routes.account_login_url }}{%- endif -%}"
|
||||
class="menu-drawer__account link focus-inset h5 medium-hide large-up-hide"
|
||||
rel="nofollow"
|
||||
>
|
||||
{%- if section.settings.enable_customer_avatar -%}
|
||||
<account-icon>
|
||||
{%- if customer and customer.has_avatar? -%}
|
||||
{{ customer | avatar }}
|
||||
{%- else -%}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-account.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</account-icon>
|
||||
{%- else -%}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-account.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- liquid
|
||||
if customer
|
||||
echo 'customer.account_fallback' | t
|
||||
else
|
||||
echo 'customer.log_in' | t
|
||||
endif
|
||||
-%}
|
||||
</a>
|
||||
{%- endif -%}
|
||||
{%- if localization.available_countries or localization.available_languages -%}
|
||||
<div class="menu-drawer__localization header-localization">
|
||||
{%- if localization.available_countries and localization.available_countries.size > 1 -%}
|
||||
<localization-form>
|
||||
{%- form 'localization', id: 'HeaderCountryMobileForm', class: 'localization-form' -%}
|
||||
<div>
|
||||
<h2 class="visually-hidden" id="HeaderCountryMobileLabel">
|
||||
{{ 'localization.country_label' | t }}
|
||||
</h2>
|
||||
{%- render 'country-localization', localPosition: 'HeaderCountryMobile' -%}
|
||||
</div>
|
||||
{%- endform -%}
|
||||
</localization-form>
|
||||
{% endif %}
|
||||
|
||||
{%- if localization.available_languages and localization.available_languages.size > 1 -%}
|
||||
<localization-form>
|
||||
{%- form 'localization', id: 'HeaderLanguageMobileForm', class: 'localization-form' -%}
|
||||
<div>
|
||||
<h2 class="visually-hidden" id="HeaderLanguageMobileLabel">
|
||||
{{ 'localization.language_label' | t }}
|
||||
</h2>
|
||||
{%- render 'language-localization', localPosition: 'HeaderLanguageMobile' -%}
|
||||
</div>
|
||||
{%- endform -%}
|
||||
</localization-form>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<ul class="list list-social list-unstyled" role="list">
|
||||
{%- if settings.social_twitter_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_twitter_link }}" class="list-social__link link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-twitter.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.twitter' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_facebook_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_facebook_link }}" class="list-social__link link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-facebook.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.facebook' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_pinterest_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_pinterest_link }}" class="list-social__link link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-pinterest.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.pinterest' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_instagram_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_instagram_link }}" class="list-social__link link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-instagram.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.instagram' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_tiktok_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_tiktok_link }}" class="list-social__link link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-tiktok.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.tiktok' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_tumblr_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_tumblr_link }}" class="list-social__link link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-tumblr.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.tumblr' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_snapchat_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_snapchat_link }}" class="list-social__link link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-snapchat.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.snapchat' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_youtube_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_youtube_link }}" class="list-social__link link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-youtube.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.youtube' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_vimeo_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_vimeo_link }}" class="list-social__link link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-vimeo.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.vimeo' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</header-drawer>
|
||||
@@ -0,0 +1,103 @@
|
||||
{% comment %}
|
||||
Renders a standard dropdown style menu for the header.
|
||||
|
||||
Usage:
|
||||
{% render 'header-dropdown-menu' %}
|
||||
{% endcomment %}
|
||||
|
||||
<nav class="header__inline-menu">
|
||||
<ul class="list-menu list-menu--inline" role="list">
|
||||
{%- for link in section.settings.menu.links -%}
|
||||
<li>
|
||||
{%- if link.links != blank -%}
|
||||
<header-menu>
|
||||
<details id="Details-HeaderMenu-{{ forloop.index }}">
|
||||
<summary
|
||||
id="HeaderMenu-{{ link.handle }}"
|
||||
class="header__menu-item list-menu__item link focus-inset"
|
||||
>
|
||||
<span
|
||||
{%- if link.child_active %}
|
||||
class="header__active-menu-item"
|
||||
{% endif %}
|
||||
>
|
||||
{{- link.title | escape -}}
|
||||
</span>
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</summary>
|
||||
<ul
|
||||
id="HeaderMenu-MenuList-{{ forloop.index }}"
|
||||
class="header__submenu list-menu list-menu--disclosure color-{{ section.settings.menu_color_scheme }} gradient caption-large motion-reduce global-settings-popup"
|
||||
role="list"
|
||||
tabindex="-1"
|
||||
>
|
||||
{%- for childlink in link.links -%}
|
||||
<li>
|
||||
{%- if childlink.links == blank -%}
|
||||
<a
|
||||
id="HeaderMenu-{{ link.handle }}-{{ childlink.handle }}"
|
||||
href="{{ childlink.url }}"
|
||||
class="header__menu-item list-menu__item link link--text focus-inset caption-large{% if childlink.current %} list-menu__item--active{% endif %}"
|
||||
{% if childlink.current %}
|
||||
aria-current="page"
|
||||
{% endif %}
|
||||
>
|
||||
{{ childlink.title | escape }}
|
||||
</a>
|
||||
{%- else -%}
|
||||
<details id="Details-HeaderSubMenu-{{ link.handle }}-{{ childlink.handle }}">
|
||||
<summary
|
||||
id="HeaderMenu-{{ link.handle }}-{{ childlink.handle }}"
|
||||
class="header__menu-item link link--text list-menu__item focus-inset caption-large"
|
||||
>
|
||||
<span>{{ childlink.title | escape }}</span>
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</summary>
|
||||
<ul
|
||||
id="HeaderMenu-SubMenuList-{{ link.handle }}-{{ childlink.handle }}-{{ grandchildlink.handle }}"
|
||||
class="header__submenu list-menu motion-reduce"
|
||||
>
|
||||
{%- for grandchildlink in childlink.links -%}
|
||||
<li>
|
||||
<a
|
||||
id="HeaderMenu-{{ link.handle }}-{{ childlink.handle }}-{{ grandchildlink.handle }}"
|
||||
href="{{ grandchildlink.url }}"
|
||||
class="header__menu-item list-menu__item link link--text focus-inset caption-large{% if grandchildlink.current %} list-menu__item--active{% endif %}"
|
||||
{% if grandchildlink.current %}
|
||||
aria-current="page"
|
||||
{% endif %}
|
||||
>
|
||||
{{ grandchildlink.title | escape }}
|
||||
</a>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</details>
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</details>
|
||||
</header-menu>
|
||||
{%- else -%}
|
||||
<a
|
||||
id="HeaderMenu-{{ link.handle }}"
|
||||
href="{{ link.url }}"
|
||||
class="header__menu-item list-menu__item link link--text focus-inset"
|
||||
{% if link.current %}
|
||||
aria-current="page"
|
||||
{% endif %}
|
||||
>
|
||||
<span
|
||||
{%- if link.current %}
|
||||
class="header__active-menu-item"
|
||||
{% endif %}
|
||||
>
|
||||
{{- link.title | escape -}}
|
||||
</span>
|
||||
</a>
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</nav>
|
||||
@@ -0,0 +1,94 @@
|
||||
{% comment %}
|
||||
Renders a megamenu for the header.
|
||||
|
||||
Usage:
|
||||
{% render 'header-mega-menu' %}
|
||||
{% endcomment %}
|
||||
|
||||
<nav class="header__inline-menu">
|
||||
<ul class="list-menu list-menu--inline" role="list">
|
||||
{%- for link in section.settings.menu.links -%}
|
||||
<li>
|
||||
{%- if link.links != blank -%}
|
||||
<header-menu>
|
||||
<details id="Details-HeaderMenu-{{ forloop.index }}" class="mega-menu">
|
||||
<summary
|
||||
id="HeaderMenu-{{ link.handle }}"
|
||||
class="header__menu-item list-menu__item link focus-inset"
|
||||
>
|
||||
<span
|
||||
{%- if link.child_active %}
|
||||
class="header__active-menu-item"
|
||||
{% endif %}
|
||||
>
|
||||
{{- link.title | escape -}}
|
||||
</span>
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</summary>
|
||||
<div
|
||||
id="MegaMenu-Content-{{ forloop.index }}"
|
||||
class="mega-menu__content color-{{ section.settings.menu_color_scheme }} gradient motion-reduce global-settings-popup"
|
||||
tabindex="-1"
|
||||
>
|
||||
<ul
|
||||
class="mega-menu__list page-width{% if link.levels == 1 %} mega-menu__list--condensed{% endif %}"
|
||||
role="list"
|
||||
>
|
||||
{%- for childlink in link.links -%}
|
||||
<li>
|
||||
<a
|
||||
id="HeaderMenu-{{ link.handle }}-{{ childlink.handle }}"
|
||||
href="{{ childlink.url }}"
|
||||
class="mega-menu__link mega-menu__link--level-2 link{% if childlink.current %} mega-menu__link--active{% endif %}"
|
||||
{% if childlink.current %}
|
||||
aria-current="page"
|
||||
{% endif %}
|
||||
>
|
||||
{{ childlink.title | escape }}
|
||||
</a>
|
||||
{%- if childlink.links != blank -%}
|
||||
<ul class="list-unstyled" role="list">
|
||||
{%- for grandchildlink in childlink.links -%}
|
||||
<li>
|
||||
<a
|
||||
id="HeaderMenu-{{ link.handle }}-{{ childlink.handle }}-{{ grandchildlink.handle }}"
|
||||
href="{{ grandchildlink.url }}"
|
||||
class="mega-menu__link link{% if grandchildlink.current %} mega-menu__link--active{% endif %}"
|
||||
{% if grandchildlink.current %}
|
||||
aria-current="page"
|
||||
{% endif %}
|
||||
>
|
||||
{{ grandchildlink.title | escape }}
|
||||
</a>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</div>
|
||||
</details>
|
||||
</header-menu>
|
||||
{%- else -%}
|
||||
<a
|
||||
id="HeaderMenu-{{ link.handle }}"
|
||||
href="{{ link.url }}"
|
||||
class="header__menu-item list-menu__item link link--text focus-inset"
|
||||
{% if link.current %}
|
||||
aria-current="page"
|
||||
{% endif %}
|
||||
>
|
||||
<span
|
||||
{%- if link.current %}
|
||||
class="header__active-menu-item"
|
||||
{% endif %}
|
||||
>
|
||||
{{- link.title | escape -}}
|
||||
</span>
|
||||
</a>
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</nav>
|
||||
@@ -0,0 +1,108 @@
|
||||
{% comment %}
|
||||
Renders a header search modal. Should be used with 'header.liquid'
|
||||
|
||||
Accepts:
|
||||
- input_id: {String} Id for the search input element (required)
|
||||
|
||||
Usage:
|
||||
{% render 'header-search', input_id: 'My-Id'%}
|
||||
{% endcomment %}
|
||||
|
||||
<details-modal class="header__search">
|
||||
<details>
|
||||
<summary
|
||||
class="header__icon header__icon--search header__icon--summary link focus-inset modal__toggle"
|
||||
aria-haspopup="dialog"
|
||||
aria-label="{{ 'general.search.search' | t }}"
|
||||
>
|
||||
<span>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-search.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="svg-wrapper header__icon-close">
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</span>
|
||||
</summary>
|
||||
<div
|
||||
class="search-modal modal__content gradient"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label="{{ 'general.search.search' | t }}"
|
||||
>
|
||||
<div class="modal-overlay"></div>
|
||||
<div
|
||||
class="search-modal__content{% if settings.inputs_shadow_vertical_offset != 0 and settings.inputs_shadow_vertical_offset < 0 %} search-modal__content-top{% else %} search-modal__content-bottom{% endif %}"
|
||||
tabindex="-1"
|
||||
>
|
||||
{%- if settings.predictive_search_enabled -%}
|
||||
<predictive-search class="search-modal__form" data-loading-text="{{ 'accessibility.loading' | t }}">
|
||||
{%- else -%}
|
||||
<search-form class="search-modal__form">
|
||||
{%- endif -%}
|
||||
<form action="{{ routes.search_url }}" method="get" role="search" class="search search-modal__form">
|
||||
<div class="field">
|
||||
<input
|
||||
class="search__input field__input"
|
||||
id="{{ input_id }}"
|
||||
type="search"
|
||||
name="q"
|
||||
value="{{ search.terms | escape }}"
|
||||
placeholder="{{ 'general.search.search' | t }}"
|
||||
{%- if settings.predictive_search_enabled -%}
|
||||
role="combobox"
|
||||
aria-expanded="false"
|
||||
aria-owns="predictive-search-results"
|
||||
aria-controls="predictive-search-results"
|
||||
aria-haspopup="listbox"
|
||||
aria-autocomplete="list"
|
||||
autocorrect="off"
|
||||
autocomplete="off"
|
||||
autocapitalize="off"
|
||||
spellcheck="false"
|
||||
{%- endif -%}
|
||||
>
|
||||
<label class="field__label" for="{{ input_id }}">{{ 'general.search.search' | t }}</label>
|
||||
<input type="hidden" name="options[prefix]" value="last">
|
||||
<button
|
||||
type="reset"
|
||||
class="reset__button field__button{% if search.terms == blank %} hidden{% endif %}"
|
||||
aria-label="{{ 'general.search.reset' | t }}"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-reset.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
<button class="search__button field__button" aria-label="{{ 'general.search.search' | t }}">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-search.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{%- if settings.predictive_search_enabled -%}
|
||||
<div class="predictive-search predictive-search--header" tabindex="-1" data-predictive-search>
|
||||
{%- render 'loading-spinner', class: 'predictive-search__loading-state' -%}
|
||||
</div>
|
||||
|
||||
<span class="predictive-search-status visually-hidden" role="status" aria-hidden="true"></span>
|
||||
{%- endif -%}
|
||||
</form>
|
||||
{%- if settings.predictive_search_enabled -%}
|
||||
</predictive-search>
|
||||
{%- else -%}
|
||||
</search-form>
|
||||
{%- endif -%}
|
||||
<button
|
||||
type="button"
|
||||
class="search-modal__close-button modal__close-button link link--text focus-inset"
|
||||
aria-label="{{ 'accessibility.close' | t }}"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</details-modal>
|
||||
@@ -0,0 +1,4 @@
|
||||
{%- if icon != 'none' -%}
|
||||
{%- assign file = icon | replace: '_', '-' | prepend: 'icon-' | append: '.svg' -%}
|
||||
<span class="svg-wrapper">{{ file | inline_asset_content }}</span>
|
||||
{%- endif -%}
|
||||
@@ -0,0 +1,109 @@
|
||||
{% comment %}
|
||||
Renders icon with text block
|
||||
|
||||
Accepts:
|
||||
- block: {Object} passes in the block information.
|
||||
|
||||
|
||||
Usage:
|
||||
{% render 'icon-with-text',
|
||||
block: block
|
||||
%}
|
||||
{% endcomment %}
|
||||
{%- liquid
|
||||
assign heading_1_empty = false
|
||||
assign heading_2_empty = false
|
||||
assign heading_3_empty = false
|
||||
assign text_only_all_items = true
|
||||
|
||||
if block.settings.heading_1 == empty
|
||||
assign heading_1_empty = true
|
||||
endif
|
||||
|
||||
if block.settings.heading_2 == empty
|
||||
assign heading_2_empty = true
|
||||
endif
|
||||
|
||||
if block.settings.heading_3 == empty
|
||||
assign heading_3_empty = true
|
||||
endif
|
||||
|
||||
if heading_1_empty == false and block.settings.icon_1 != 'none' or block.settings.image_1 != null
|
||||
assign text_only_all_items = false
|
||||
elsif heading_2_empty == false and block.settings.icon_2 != 'none' or block.settings.image_2 != null
|
||||
assign text_only_all_items = false
|
||||
elsif heading_3_empty == false and block.settings.icon_3 != 'none' or block.settings.image_3 != null
|
||||
assign text_only_all_items = false
|
||||
endif
|
||||
-%}
|
||||
<ul
|
||||
class="icon-with-text icon-with-text--{{ block.settings.layout }} list-unstyled{% if text_only_all_items %} icon-with-text--text-only{% endif %}"
|
||||
{{ block.shopify_attributes }}
|
||||
>
|
||||
{%- unless heading_1_empty -%}
|
||||
<li class="icon-with-text__item">
|
||||
{%- if block.settings.image_1 == null -%}
|
||||
{%- render 'icon-accordion', icon: block.settings.icon_1 -%}
|
||||
{%- else -%}
|
||||
<img
|
||||
src="{{ block.settings.image_1 | image_url }}"
|
||||
{% if block.settings.image_1.alt != blank %}
|
||||
alt="{{ block.settings.image_1.alt | escape }}"
|
||||
{% else %}
|
||||
role="presentation"
|
||||
{% endif %}
|
||||
height="auto"
|
||||
width="auto"
|
||||
loading="lazy"
|
||||
>
|
||||
{%- endif -%}
|
||||
<span class="h4 inline-richtext">
|
||||
{{- block.settings.heading_1 -}}
|
||||
</span>
|
||||
</li>
|
||||
{%- endunless -%}
|
||||
{%- unless heading_2_empty -%}
|
||||
<li class="icon-with-text__item">
|
||||
{%- if block.settings.image_2 == null -%}
|
||||
{% render 'icon-accordion', icon: block.settings.icon_2 -%}
|
||||
{%- else -%}
|
||||
<img
|
||||
src="{{ block.settings.image_2 | image_url }}"
|
||||
{% if block.settings.image_2.alt != blank %}
|
||||
alt="{{ block.settings.image_2.alt | escape }}"
|
||||
{% else %}
|
||||
role="presentation"
|
||||
{% endif %}
|
||||
height="auto"
|
||||
width="auto"
|
||||
loading="lazy"
|
||||
>
|
||||
{%- endif -%}
|
||||
<span class="h4 inline-richtext">
|
||||
{{- block.settings.heading_2 -}}
|
||||
</span>
|
||||
</li>
|
||||
{%- endunless -%}
|
||||
{%- unless heading_3_empty -%}
|
||||
<li class="icon-with-text__item">
|
||||
{%- if block.settings.image_3 == null -%}
|
||||
{% render 'icon-accordion', icon: block.settings.icon_3 -%}
|
||||
{%- else -%}
|
||||
<img
|
||||
src="{{ block.settings.image_3 | image_url }}"
|
||||
{% if block.settings.image_3.alt != blank %}
|
||||
alt="{{ block.settings.image_3.alt | escape }}"
|
||||
{% else %}
|
||||
role="presentation"
|
||||
{% endif %}
|
||||
height="auto"
|
||||
width="auto"
|
||||
loading="lazy"
|
||||
>
|
||||
{%- endif -%}
|
||||
<span class="h4 inline-richtext">
|
||||
{{- block.settings.heading_3 -}}
|
||||
</span>
|
||||
</li>
|
||||
{%- endunless -%}
|
||||
</ul>
|
||||
@@ -0,0 +1,49 @@
|
||||
{%- comment -%}
|
||||
Renders the language picker for the localization form
|
||||
|
||||
Accepts:
|
||||
- localPosition: pass in the position in which the form is coming up to create specific IDs
|
||||
{%- endcomment -%}
|
||||
|
||||
<div class="disclosure">
|
||||
<button
|
||||
type="button"
|
||||
class="disclosure__button localization-form__select localization-selector link link--text caption-large"
|
||||
aria-expanded="false"
|
||||
aria-controls="{{ localPosition }}List"
|
||||
aria-describedby="{{ localPosition }}Label"
|
||||
>
|
||||
<span>{{ localization.language.endonym_name | capitalize }}</span>
|
||||
{{ 'icon-caret.svg' | inline_asset_content }}
|
||||
</button>
|
||||
<div class="disclosure__list-wrapper language-selector" hidden>
|
||||
<ul id="{{ localPosition }}List" role="list" class="disclosure__list list-unstyled">
|
||||
{%- for language in localization.available_languages -%}
|
||||
<li class="disclosure__item" tabindex="-1">
|
||||
<a
|
||||
class="link link--text disclosure__link caption-large focus-inset"
|
||||
href="#"
|
||||
hreflang="{{ language.iso_code }}"
|
||||
lang="{{ language.iso_code }}"
|
||||
{% if language.iso_code == localization.language.iso_code %}
|
||||
aria-current="true"
|
||||
{% endif %}
|
||||
data-value="{{ language.iso_code }}"
|
||||
>
|
||||
<span
|
||||
{% if language.iso_code != localization.language.iso_code %}
|
||||
class="visibility-hidden"
|
||||
{% endif %}
|
||||
>
|
||||
{{- 'icon-checkmark.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span>
|
||||
{{ language.endonym_name | capitalize }}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="locale_code" value="{{ localization.language.iso_code }}">
|
||||
@@ -0,0 +1,12 @@
|
||||
{% comment %}
|
||||
Renders loading-spinner.
|
||||
Accepts:
|
||||
- class: {string} css classes to replace the default ones (optional)
|
||||
|
||||
Usage:
|
||||
{% render 'loading-spinner' %}
|
||||
{% endcomment %}
|
||||
|
||||
<div class="{% if class %}{{ class }}{% else %}loading__spinner hidden{% endif %}">
|
||||
{{ 'loading-spinner.svg' | inline_asset_content }}
|
||||
</div>
|
||||
@@ -0,0 +1,39 @@
|
||||
{%- liquid
|
||||
assign og_title = page_title | default: shop.name
|
||||
assign og_url = canonical_url | default: request.origin
|
||||
assign og_type = 'website'
|
||||
assign og_description = page_description | default: shop.description | default: shop.name
|
||||
|
||||
if request.page_type == 'product'
|
||||
assign og_type = 'product'
|
||||
elsif request.page_type == 'article'
|
||||
assign og_type = 'article'
|
||||
elsif request.page_type == 'password'
|
||||
assign og_url = request.origin
|
||||
endif
|
||||
%}
|
||||
|
||||
<meta property="og:site_name" content="{{ shop.name }}">
|
||||
<meta property="og:url" content="{{ og_url }}">
|
||||
<meta property="og:title" content="{{ og_title | escape }}">
|
||||
<meta property="og:type" content="{{ og_type }}">
|
||||
<meta property="og:description" content="{{ og_description | escape }}">
|
||||
|
||||
{%- if page_image -%}
|
||||
<meta property="og:image" content="http:{{ page_image | image_url }}">
|
||||
<meta property="og:image:secure_url" content="https:{{ page_image | image_url }}">
|
||||
<meta property="og:image:width" content="{{ page_image.width }}">
|
||||
<meta property="og:image:height" content="{{ page_image.height }}">
|
||||
{%- endif -%}
|
||||
|
||||
{%- if request.page_type == 'product' -%}
|
||||
<meta property="og:price:amount" content="{{ product.price | money_without_currency | strip_html }}">
|
||||
<meta property="og:price:currency" content="{{ cart.currency.iso_code }}">
|
||||
{%- endif -%}
|
||||
|
||||
{%- if settings.social_twitter_link != blank -%}
|
||||
<meta name="twitter:site" content="{{ settings.social_twitter_link | split: 'twitter.com/' | last | prepend: '@' }}">
|
||||
{%- endif -%}
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="{{ og_title | escape }}">
|
||||
<meta name="twitter:description" content="{{ og_description | escape }}">
|
||||
@@ -0,0 +1,78 @@
|
||||
{% comment %}
|
||||
Renders a set of links for paginated results. Must be used within paginate tags.
|
||||
|
||||
Usage:
|
||||
{% paginate results by 2 %}
|
||||
{% render 'pagination', paginate: paginate, anchor: '#yourID' %}
|
||||
{% endpaginate %}
|
||||
|
||||
Accepts:
|
||||
- paginate: {Object}
|
||||
- anchor: {String} (optional) This can be added so that on page reload it takes you to wherever you've placed your anchor tag.
|
||||
{% endcomment %}
|
||||
|
||||
{{ 'component-pagination.css' | asset_url | stylesheet_tag }}
|
||||
|
||||
{%- if paginate.parts.size > 0 -%}
|
||||
<div class="pagination-wrapper" data-page="{{ paginate.current_page }}">
|
||||
<nav class="pagination" role="navigation" aria-label="{{ 'general.pagination.label' | t }}">
|
||||
<ul class="pagination__list list-unstyled" role="list">
|
||||
{%- if paginate.previous -%}
|
||||
<li>
|
||||
<a
|
||||
href="{{ paginate.previous.url }}{{ anchor }}"
|
||||
class="pagination__item pagination__item--next pagination__item-arrow link motion-reduce"
|
||||
aria-label="{{ 'general.pagination.previous' | t }}"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
|
||||
{%- for part in paginate.parts -%}
|
||||
<li>
|
||||
{%- if part.is_link -%}
|
||||
<a
|
||||
href="{{ part.url }}{{ anchor }}"
|
||||
class="pagination__item link"
|
||||
aria-label="{{ 'general.pagination.page' | t: number: part.title }}"
|
||||
>
|
||||
{{- part.title -}}
|
||||
</a>
|
||||
{%- else -%}
|
||||
{%- if part.title == paginate.current_page -%}
|
||||
<a
|
||||
role="link"
|
||||
aria-disabled="true"
|
||||
class="pagination__item pagination__item--current light"
|
||||
aria-current="page"
|
||||
aria-label="{{ 'general.pagination.page' | t: number: part.title }}"
|
||||
>
|
||||
{{- part.title -}}
|
||||
</a>
|
||||
{%- else -%}
|
||||
<span class="pagination__item">{{ part.title }}</span>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
|
||||
{%- if paginate.next -%}
|
||||
<li>
|
||||
<a
|
||||
href="{{ paginate.next.url }}{{ anchor }}"
|
||||
class="pagination__item pagination__item--prev pagination__item-arrow link motion-reduce"
|
||||
aria-label="{{ 'general.pagination.next' | t }}"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
@@ -0,0 +1,45 @@
|
||||
<span class="field-currency">{{ cart.currency.symbol }}</span>
|
||||
|
||||
<div class="field">
|
||||
<input
|
||||
class="field__input"
|
||||
name="{{ filter.min_value.param_name }}"
|
||||
id="{{ id_prefix }}{{ filter.label | escape }}-GTE"
|
||||
{%- if filter.min_value.value -%}
|
||||
value="{{ filter.min_value.value | money_without_currency }}"
|
||||
{%- endif -%}
|
||||
type="text"
|
||||
inputmode="decimal"
|
||||
placeholder="0"
|
||||
data-pattern="\d| |,|\."
|
||||
data-min="0"
|
||||
data-max="{{ filter.range_max | money_without_currency }}"
|
||||
>
|
||||
<label class="field__label" for="{{ id_prefix }}{{ filter.label | escape }}-GTE">
|
||||
{{- 'products.facets.from' | t -}}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{%- if filter_type != 'vertical' -%}
|
||||
<span class="field-currency">{{ cart.currency.symbol }}</span>
|
||||
{%- endif -%}
|
||||
|
||||
<div class="field">
|
||||
<input
|
||||
class="field__input"
|
||||
name="{{ filter.max_value.param_name }}"
|
||||
id="{{ id_prefix }}{{ filter.label | escape }}-LTE"
|
||||
{%- if filter.max_value.value -%}
|
||||
value="{{ filter.max_value.value | money_without_currency }}"
|
||||
{%- endif -%}
|
||||
type="text"
|
||||
inputmode="decimal"
|
||||
placeholder="{{ filter.range_max | money_without_currency }}"
|
||||
data-pattern="\d| |,|\."
|
||||
data-min="0"
|
||||
data-max="{{ filter.range_max | money_without_currency }}"
|
||||
>
|
||||
<label class="field__label" for="{{ id_prefix }}{{ filter.label | escape }}-LTE">
|
||||
{{- 'products.facets.to' | t -}}
|
||||
</label>
|
||||
</div>
|
||||
@@ -0,0 +1,125 @@
|
||||
{% comment %}
|
||||
Renders a list of product's price (regular, sale)
|
||||
|
||||
Accepts:
|
||||
- product: {Object} Product Liquid object (optional)
|
||||
- placeholder: {Boolean} Renders a placeholder price (optional)
|
||||
- use_variant: {Boolean} Renders selected or first variant price instead of overall product pricing (optional)
|
||||
- show_badges: {Boolean} Renders 'Sale' and 'Sold Out' tags if the product matches the condition (optional)
|
||||
- price_class: {String} Adds a price class to the price element (optional)
|
||||
- show_compare_at_price: {Boolean} Renders the compare at price if the product matches the condition (optional)
|
||||
|
||||
Usage:
|
||||
{% render 'price', product: product %}
|
||||
{% endcomment %}
|
||||
{%- liquid
|
||||
if use_variant
|
||||
assign target = product.selected_or_first_available_variant
|
||||
elsif placeholder
|
||||
assign target = null
|
||||
else
|
||||
assign target = product
|
||||
endif
|
||||
|
||||
assign compare_at_price = target.compare_at_price
|
||||
assign price = target.price | default: 1999
|
||||
assign price_min = product.price_min
|
||||
assign price_max = product.price_max
|
||||
assign available = target.available | default: false
|
||||
assign money_price = price | money
|
||||
assign money_price_min = price_min | money
|
||||
assign money_price_max = price_max | money
|
||||
if settings.currency_code_enabled
|
||||
assign money_price = price | money_with_currency
|
||||
assign money_price_min = price_min | money_with_currency
|
||||
assign money_price_max = price_max | money_with_currency
|
||||
endif
|
||||
|
||||
if target == product and product.price_varies
|
||||
assign money_price = 'products.product.price.from_price_html' | t: price: money_price
|
||||
endif
|
||||
-%}
|
||||
|
||||
{%- unless target == null and placeholder == null -%}
|
||||
<div
|
||||
class="
|
||||
price
|
||||
{%- if price_class %} {{ price_class }}{% endif -%}
|
||||
{%- if available == false %} price--sold-out{% endif -%}
|
||||
{%- if compare_at_price > price and product.quantity_price_breaks_configured? != true %} price--on-sale{% endif -%}
|
||||
{%- if compare_at_price > price and product.quantity_price_breaks_configured? %} volume-pricing--sale-badge{% endif -%}
|
||||
{%- if product.price_varies == false and product.compare_at_price_varies %} price--no-compare{% endif -%}
|
||||
{%- if show_badges %} price--show-badge{% endif -%}
|
||||
"
|
||||
>
|
||||
<div class="price__container">
|
||||
{%- comment -%}
|
||||
Explanation of description list:
|
||||
- div.price__regular: Displayed when there are no variants on sale
|
||||
- div.price__sale: Displayed when a variant is a sale
|
||||
{%- endcomment -%}
|
||||
<div class="price__regular">
|
||||
{%- if product.quantity_price_breaks_configured? -%}
|
||||
{%- if show_compare_at_price and compare_at_price -%}
|
||||
{%- unless product.price_varies == false and product.compare_at_price_varies %}
|
||||
<span class="visually-hidden visually-hidden--inline">
|
||||
{{- 'products.product.price.regular_price' | t -}}
|
||||
</span>
|
||||
<span>
|
||||
<s class="price-item price-item--regular variant-item__old-price">
|
||||
{% if settings.currency_code_enabled %}
|
||||
{{ compare_at_price | money_with_currency }}
|
||||
{% else %}
|
||||
{{ compare_at_price | money }}
|
||||
{% endif %}
|
||||
</s>
|
||||
</span>
|
||||
{%- endunless -%}
|
||||
{%- endif -%}
|
||||
<span class="visually-hidden visually-hidden--inline">{{ 'products.product.price.regular_price' | t }}</span>
|
||||
<span class="price-item price-item--regular">
|
||||
{{-
|
||||
'products.product.volume_pricing.price_range'
|
||||
| t: minimum: money_price_min, maximum: money_price_max
|
||||
-}}
|
||||
</span>
|
||||
{%- else -%}
|
||||
<span class="visually-hidden visually-hidden--inline">{{ 'products.product.price.regular_price' | t }}</span>
|
||||
<span class="price-item price-item--regular">
|
||||
{{ money_price }}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<div class="price__sale">
|
||||
{%- unless product.price_varies == false and product.compare_at_price_varies %}
|
||||
<span class="visually-hidden visually-hidden--inline">{{ 'products.product.price.regular_price' | t }}</span>
|
||||
<span>
|
||||
<s class="price-item price-item--regular">
|
||||
{% if settings.currency_code_enabled %}
|
||||
{{ compare_at_price | money_with_currency }}
|
||||
{% else %}
|
||||
{{ compare_at_price | money }}
|
||||
{% endif %}
|
||||
</s>
|
||||
</span>
|
||||
{%- endunless -%}
|
||||
<span class="visually-hidden visually-hidden--inline">{{ 'products.product.price.sale_price' | t }}</span>
|
||||
<span class="price-item price-item--sale price-item--last">
|
||||
{{ money_price }}
|
||||
</span>
|
||||
</div>
|
||||
{%- if product.selected_or_first_available_variant.unit_price_measurement -%}
|
||||
{% render 'unit-price', price: product.selected_or_first_available_variant.unit_price, measurement: product.selected_or_first_available_variant.unit_price_measurement %}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- if show_badges -%}
|
||||
<span class="badge price__badge-sale color-{{ settings.sale_badge_color_scheme }}">
|
||||
{{ 'products.product.on_sale' | t }}
|
||||
</span>
|
||||
|
||||
<span class="badge price__badge-sold-out color-{{ settings.sold_out_badge_color_scheme }}">
|
||||
{{ 'products.product.sold_out' | t }}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{% endunless %}
|
||||
@@ -0,0 +1,108 @@
|
||||
{%- assign disclosure_surface = surface | default: 'product_page' -%}
|
||||
{%- assign disclosures = product.metafields.shopify.disclosure.value -%}
|
||||
{%- assign summary_html = '' -%}
|
||||
{%- assign details_html = '' -%}
|
||||
{%- assign rendered_disclosures_count = 0 -%}
|
||||
|
||||
{%- if disclosures != blank -%}
|
||||
{%- for disclosure in disclosures -%}
|
||||
{%- assign surfaces = disclosure.display_preferences.value.surfaces -%}
|
||||
|
||||
{%- if surfaces contains disclosure_surface -%}
|
||||
{%- assign title = disclosure.title.value -%}
|
||||
{%- assign img = disclosure.symbol.value -%}
|
||||
{%- assign content = disclosure.content -%}
|
||||
|
||||
{%- capture summary_item -%}
|
||||
{%- if rendered_disclosures_count > 0 -%}
|
||||
<span class="disclosures-separator">•</span>
|
||||
{%- endif -%}
|
||||
<span class="disclosures-summary-item">
|
||||
{%- if img != blank -%}
|
||||
<img
|
||||
src="{{ img | image_url: width: 40 }}"
|
||||
srcset="{{ img | image_url: width: 20 }} 1x, {{ img | image_url: width: 40 }} 2x, {{ img | image_url: width: 60 }} 3x"
|
||||
alt=""
|
||||
class="disclosures__icon"
|
||||
width="40"
|
||||
height="31"
|
||||
loading="lazy"
|
||||
>
|
||||
{%- endif -%}
|
||||
<span class="disclosures-summary-item__title">{{ title }}</span>
|
||||
<span class="disclosures-summary-item__open-title">{{ title }}</span>
|
||||
</span>
|
||||
{%- endcapture -%}
|
||||
|
||||
{%- capture details_item -%}
|
||||
<div class="disclosures-item">
|
||||
{%- if rendered_disclosures_count > 0 -%}
|
||||
{%- if title != blank or img != blank -%}
|
||||
<div class="disclosures-item__header">
|
||||
{%- if img != blank -%}
|
||||
<img
|
||||
src="{{ img | image_url: width: 40 }}"
|
||||
srcset="{{ img | image_url: width: 20 }} 1x, {{ img | image_url: width: 40 }} 2x, {{ img | image_url: width: 60 }} 3x"
|
||||
alt=""
|
||||
class="disclosures__icon"
|
||||
width="40"
|
||||
height="31"
|
||||
loading="lazy"
|
||||
>
|
||||
{%- endif -%}
|
||||
{%- if title != blank -%}
|
||||
<span>{{ title }}</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
<div class="disclosures-item__content">
|
||||
{{ content | metafield_tag }}
|
||||
</div>
|
||||
</div>
|
||||
{%- endcapture -%}
|
||||
|
||||
{%- capture summary_html -%}{{ summary_html }}{{ summary_item }}{%- endcapture -%}
|
||||
{%- capture details_html -%}{{ details_html }}{{ details_item }}{%- endcapture -%}
|
||||
{%- assign rendered_disclosures_count = rendered_disclosures_count | plus: 1 -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
|
||||
{%- if rendered_disclosures_count > 0 -%}
|
||||
{{ 'component-disclosures.css' | asset_url | stylesheet_tag }}
|
||||
|
||||
<div
|
||||
class="disclosures spacing-style"
|
||||
{% if block != blank %}
|
||||
{{ block.shopify_attributes }}
|
||||
{% endif %}
|
||||
>
|
||||
{%- if heading != blank -%}
|
||||
<h3 class="disclosures__heading {{ heading_size }}">
|
||||
{{ heading | escape }}
|
||||
</h3>
|
||||
{%- endif -%}
|
||||
|
||||
<details
|
||||
class="disclosures__details"
|
||||
{% if open_by_default %}
|
||||
open
|
||||
{% endif %}
|
||||
>
|
||||
<summary class="disclosures__summary">
|
||||
<div class="disclosures__summary-content">
|
||||
{{ summary_html }}
|
||||
</div>
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</summary>
|
||||
|
||||
<disclosures-content class="disclosures__content">
|
||||
{{ details_html }}
|
||||
</disclosures-content>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<script src="{{ 'disclosures.js' | asset_url }}" defer="defer"></script>
|
||||
{%- endif -%}
|
||||
@@ -0,0 +1,332 @@
|
||||
{% comment %}
|
||||
Renders a product media gallery. Should be used with 'media-gallery.js'
|
||||
Also see 'product-media-modal'
|
||||
|
||||
Accepts:
|
||||
- product: {Object} Product liquid object
|
||||
- variant_images: {Array} Product images associated with a variant
|
||||
- limit: {Number} (optional) When passed, limits the number of media items to render
|
||||
|
||||
Usage:
|
||||
{% render 'product-media-gallery' %}
|
||||
{% endcomment %}
|
||||
|
||||
{%- liquid
|
||||
if section.settings.hide_variants and variant_images.size == product.media.size
|
||||
assign single_media_visible = true
|
||||
endif
|
||||
|
||||
if limit == 1
|
||||
assign single_media_visible = true
|
||||
endif
|
||||
|
||||
assign media_count = product.media.size
|
||||
if section.settings.hide_variants and media_count > 1 and variant_images.size > 0
|
||||
assign media_count = media_count | minus: variant_images.size | plus: 1
|
||||
endif
|
||||
|
||||
if media_count == 1 or single_media_visible
|
||||
assign single_media_visible_mobile = true
|
||||
endif
|
||||
|
||||
if media_count == 0 or single_media_visible_mobile or section.settings.mobile_thumbnails == 'show' or section.settings.mobile_thumbnails == 'columns' and media_count < 3
|
||||
assign hide_mobile_slider = true
|
||||
endif
|
||||
|
||||
if section.settings.media_size == 'large'
|
||||
assign media_width = 0.65
|
||||
elsif section.settings.media_size == 'medium'
|
||||
assign media_width = 0.55
|
||||
elsif section.settings.media_size == 'small'
|
||||
assign media_width = 0.45
|
||||
endif
|
||||
-%}
|
||||
|
||||
<media-gallery
|
||||
id="MediaGallery-{{ section.id }}"
|
||||
role="region"
|
||||
{% if section.settings.enable_sticky_info %}
|
||||
class="product__column-sticky"
|
||||
{% endif %}
|
||||
aria-label="{{ 'products.product.media.gallery_viewer' | t }}"
|
||||
data-desktop-layout="{{ section.settings.gallery_layout }}"
|
||||
>
|
||||
<div id="GalleryStatus-{{ section.id }}" class="visually-hidden" role="status"></div>
|
||||
<slider-component id="GalleryViewer-{{ section.id }}" class="slider-mobile-gutter">
|
||||
<a class="skip-to-content-link button visually-hidden quick-add-hidden" href="#ProductInfo-{{ section.id }}">
|
||||
{{ 'accessibility.skip_to_product_info' | t }}
|
||||
</a>
|
||||
<ul
|
||||
id="Slider-Gallery-{{ section.id }}"
|
||||
class="product__media-list contains-media grid grid--peek list-unstyled slider slider--mobile"
|
||||
role="list"
|
||||
>
|
||||
{%- if product.selected_or_first_available_variant.featured_media != null -%}
|
||||
{%- assign featured_media = product.selected_or_first_available_variant.featured_media -%}
|
||||
<li
|
||||
id="Slide-{{ section.id }}-{{ featured_media.id }}"
|
||||
class="product__media-item grid__item slider__slide is-active{% if single_media_visible %} product__media-item--single{% endif %}{% if featured_media.media_type != 'image' %} product__media-item--full{% endif %}{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--fade-in{% endif %}"
|
||||
data-media-id="{{ section.id }}-{{ featured_media.id }}"
|
||||
>
|
||||
{%- assign media_position = 1 -%}
|
||||
{% render 'product-thumbnail',
|
||||
media: featured_media,
|
||||
media_count: media_count,
|
||||
position: media_position,
|
||||
desktop_layout: section.settings.gallery_layout,
|
||||
mobile_layout: section.settings.mobile_thumbnails,
|
||||
loop: section.settings.enable_video_looping,
|
||||
modal_id: section.id,
|
||||
xr_button: true,
|
||||
media_width: media_width,
|
||||
media_fit: section.settings.media_fit,
|
||||
constrain_to_viewport: section.settings.constrain_to_viewport,
|
||||
lazy_load: false
|
||||
%}
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- for media in product.media -%}
|
||||
{% if media_position >= limit
|
||||
or media_position >= 1
|
||||
and section.settings.hide_variants
|
||||
and variant_images contains media.src
|
||||
%}
|
||||
{% continue %}
|
||||
{% endif %}
|
||||
|
||||
{%- unless media.id == product.selected_or_first_available_variant.featured_media.id -%}
|
||||
<li
|
||||
id="Slide-{{ section.id }}-{{ media.id }}"
|
||||
class="product__media-item grid__item slider__slide{% if single_media_visible %} product__media-item--single{% endif %}{% if product.selected_or_first_available_variant.featured_media == nil and forloop.index == 1 %} is-active{% endif %}{% if media.media_type != 'image' %} product__media-item--full{% endif %}{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--fade-in{% endif %}"
|
||||
data-media-id="{{ section.id }}-{{ media.id }}"
|
||||
>
|
||||
{%- liquid
|
||||
assign media_position = media_position | default: 0 | plus: 1
|
||||
assign lazy_load = false
|
||||
if media_position > 1
|
||||
assign lazy_load = true
|
||||
endif
|
||||
-%}
|
||||
{% render 'product-thumbnail',
|
||||
media: media,
|
||||
media_count: media_count,
|
||||
position: media_position,
|
||||
desktop_layout: section.settings.gallery_layout,
|
||||
mobile_layout: section.settings.mobile_thumbnails,
|
||||
loop: section.settings.enable_video_looping,
|
||||
modal_id: section.id,
|
||||
xr_button: true,
|
||||
media_width: media_width,
|
||||
media_fit: section.settings.media_fit,
|
||||
constrain_to_viewport: section.settings.constrain_to_viewport,
|
||||
lazy_load: lazy_load
|
||||
%}
|
||||
</li>
|
||||
{%- endunless -%}
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
<div class="slider-buttons quick-add-hidden{% if hide_mobile_slider %} small-hide{% endif %}">
|
||||
<button
|
||||
type="button"
|
||||
class="slider-button slider-button--prev"
|
||||
name="previous"
|
||||
aria-label="{{ 'general.slider.previous_slide' | t }}"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
<div class="slider-counter caption">
|
||||
<span class="slider-counter--current">1</span>
|
||||
<span aria-hidden="true"> / </span>
|
||||
<span class="visually-hidden">{{ 'general.slider.of' | t }}</span>
|
||||
<span class="slider-counter--total">{{ media_count }}</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="slider-button slider-button--next"
|
||||
name="next"
|
||||
aria-label="{{ 'general.slider.next_slide' | t }}"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</slider-component>
|
||||
{%- if first_3d_model -%}
|
||||
<button
|
||||
class="button button--full-width product__xr-button"
|
||||
type="button"
|
||||
aria-label="{{ 'products.product.xr_button_label' | t }}"
|
||||
data-shopify-xr
|
||||
data-shopify-model3d-id="{{ first_3d_model.id }}"
|
||||
data-shopify-title="{{ product.title | escape }}"
|
||||
data-shopify-xr-hidden
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-3d-model.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{{ 'products.product.xr_button' | t }}
|
||||
</button>
|
||||
{%- endif -%}
|
||||
{%- liquid
|
||||
assign is_not_limited_to_single_item = false
|
||||
if limit == null or limit > 1
|
||||
assign is_not_limited_to_single_item = true
|
||||
endif
|
||||
-%}
|
||||
{%- if is_not_limited_to_single_item
|
||||
and media_count > 1
|
||||
and section.settings.gallery_layout contains 'thumbnail'
|
||||
or section.settings.mobile_thumbnails == 'show'
|
||||
-%}
|
||||
<slider-component
|
||||
id="GalleryThumbnails-{{ section.id }}"
|
||||
class="thumbnail-slider slider-mobile-gutter quick-add-hidden{% unless section.settings.gallery_layout contains 'thumbnail' %} medium-hide large-up-hide{% endunless %}{% if section.settings.mobile_thumbnails != 'show' %} small-hide{% endif %}{% if media_count <= 3 %} thumbnail-slider--no-slide{% endif %}"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="slider-button slider-button--prev{% if media_count <= 3 %} small-hide{% endif %}{% if media_count <= 4 %} medium-hide large-up-hide{% endif %}"
|
||||
name="previous"
|
||||
aria-label="{{ 'general.slider.previous_slide' | t }}"
|
||||
aria-controls="GalleryThumbnails-{{ section.id }}"
|
||||
data-step="3"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
<ul
|
||||
id="Slider-Thumbnails-{{ section.id }}"
|
||||
class="thumbnail-list list-unstyled slider slider--mobile{% if section.settings.gallery_layout == 'thumbnail_slider' %} slider--tablet-up{% endif %}"
|
||||
>
|
||||
{%- capture sizes -%}
|
||||
(min-width: {{ settings.page_width }}px) calc(({{ settings.page_width | minus: 100 | times: media_width | round }} - 4rem) / 4),
|
||||
(min-width: 990px) calc(({{ media_width | times: 100 }}vw - 4rem) / 4),
|
||||
(min-width: 750px) calc((100vw - 15rem) / 8),
|
||||
calc((100vw - 8rem) / 3)
|
||||
{%- endcapture -%}
|
||||
|
||||
{%- if featured_media != null -%}
|
||||
{%- liquid
|
||||
capture media_index
|
||||
if featured_media.media_type == 'model'
|
||||
increment model_index
|
||||
elsif featured_media.media_type == 'video' or featured_media.media_type == 'external_video'
|
||||
increment video_index
|
||||
elsif featured_media.media_type == 'image'
|
||||
increment image_index
|
||||
endif
|
||||
endcapture
|
||||
assign media_index = media_index | plus: 1
|
||||
-%}
|
||||
<li
|
||||
id="Slide-Thumbnails-{{ section.id }}-0"
|
||||
class="thumbnail-list__item slider__slide{% if section.settings.hide_variants and variant_images contains featured_media.src %} thumbnail-list_item--variant{% endif %}"
|
||||
data-target="{{ section.id }}-{{ featured_media.id }}"
|
||||
data-media-position="{{ media_index }}"
|
||||
>
|
||||
{%- capture thumbnail_id -%}
|
||||
Thumbnail-{{ section.id }}-0
|
||||
{%- endcapture -%}
|
||||
<button
|
||||
class="thumbnail global-media-settings global-media-settings--no-shadow"
|
||||
aria-label="{%- if featured_media.media_type == 'image' -%}{{ 'products.product.media.load_image' | t: index: media_index }}{%- elsif featured_media.media_type == 'model' -%}{{ 'products.product.media.load_model' | t: index: media_index }}{%- elsif featured_media.media_type == 'video' or featured_media.media_type == 'external_video' -%}{{ 'products.product.media.load_video' | t: index: media_index }}{%- endif -%}"
|
||||
aria-current="true"
|
||||
aria-controls="GalleryViewer-{{ section.id }}"
|
||||
aria-describedby="{{ thumbnail_id }}"
|
||||
>
|
||||
{{
|
||||
featured_media.preview_image
|
||||
| image_url: width: 416
|
||||
| image_tag:
|
||||
loading: 'lazy',
|
||||
sizes: sizes,
|
||||
widths: '54, 74, 104, 162, 208, 324, 416',
|
||||
id: thumbnail_id,
|
||||
alt: featured_media.alt
|
||||
| escape
|
||||
}}
|
||||
</button>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- for media in product.media -%}
|
||||
{%- unless media.id == product.selected_or_first_available_variant.featured_media.id -%}
|
||||
{%- liquid
|
||||
capture media_index
|
||||
if media.media_type == 'model'
|
||||
increment model_index
|
||||
elsif media.media_type == 'video' or media.media_type == 'external_video'
|
||||
increment video_index
|
||||
elsif media.media_type == 'image'
|
||||
increment image_index
|
||||
endif
|
||||
endcapture
|
||||
assign media_index = media_index | plus: 1
|
||||
-%}
|
||||
<li
|
||||
id="Slide-Thumbnails-{{ section.id }}-{{ forloop.index }}"
|
||||
class="thumbnail-list__item slider__slide{% if section.settings.hide_variants and variant_images contains media.src %} thumbnail-list_item--variant{% endif %}"
|
||||
data-target="{{ section.id }}-{{ media.id }}"
|
||||
data-media-position="{{ media_index }}"
|
||||
>
|
||||
{%- if media.media_type == 'model' -%}
|
||||
<span class="thumbnail__badge" aria-hidden="true">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-3d-model.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</span>
|
||||
{%- elsif media.media_type == 'video' or media.media_type == 'external_video' -%}
|
||||
<span class="thumbnail__badge" aria-hidden="true">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-play.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- capture thumbnail_id -%}
|
||||
Thumbnail-{{ section.id }}-{{ forloop.index }}
|
||||
{%- endcapture -%}
|
||||
<button
|
||||
class="thumbnail global-media-settings global-media-settings--no-shadow"
|
||||
aria-label="{%- if media.media_type == 'image' -%}{{ 'products.product.media.load_image' | t: index: media_index }}{%- elsif media.media_type == 'model' -%}{{ 'products.product.media.load_model' | t: index: media_index }}{%- elsif media.media_type == 'video' or media.media_type == 'external_video' -%}{{ 'products.product.media.load_video' | t: index: media_index }}{%- endif -%}"
|
||||
{% if media == product.selected_or_first_available_variant.featured_media
|
||||
or product.selected_or_first_available_variant.featured_media == null
|
||||
and forloop.index == 1
|
||||
%}
|
||||
aria-current="true"
|
||||
{% endif %}
|
||||
aria-controls="GalleryViewer-{{ section.id }}"
|
||||
aria-describedby="{{ thumbnail_id }}"
|
||||
>
|
||||
{{
|
||||
media.preview_image
|
||||
| image_url: width: 416
|
||||
| image_tag:
|
||||
loading: 'lazy',
|
||||
sizes: sizes,
|
||||
widths: '54, 74, 104, 162, 208, 324, 416',
|
||||
id: thumbnail_id,
|
||||
alt: media.alt
|
||||
| escape
|
||||
}}
|
||||
</button>
|
||||
</li>
|
||||
{%- endunless -%}
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
<button
|
||||
type="button"
|
||||
class="slider-button slider-button--next{% if media_count <= 3 %} small-hide{% endif %}{% if media_count <= 4 %} medium-hide large-up-hide{% endif %}"
|
||||
name="next"
|
||||
aria-label="{{ 'general.slider.next_slide' | t }}"
|
||||
aria-controls="GalleryThumbnails-{{ section.id }}"
|
||||
data-step="3"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
</slider-component>
|
||||
{%- endif -%}
|
||||
</media-gallery>
|
||||
@@ -0,0 +1,57 @@
|
||||
{% comment %}
|
||||
Renders a product media modal. Also see 'product-media-gallery'
|
||||
|
||||
Accepts:
|
||||
- product: {Object} Product liquid object
|
||||
- variant_images: {Array} Product images associated with a variant
|
||||
|
||||
Usage:
|
||||
{% render 'product-media-modal' %}
|
||||
{% endcomment %}
|
||||
|
||||
<product-modal id="ProductModal-{{ section.id }}" class="product-media-modal media-modal">
|
||||
<div
|
||||
class="product-media-modal__dialog color-{{ section.settings.color_scheme }} gradient"
|
||||
role="dialog"
|
||||
aria-label="{{ 'products.modal.label' | t }}"
|
||||
aria-modal="true"
|
||||
tabindex="-1"
|
||||
>
|
||||
<button
|
||||
id="ModalClose-{{ section.id }}"
|
||||
type="button"
|
||||
class="product-media-modal__toggle"
|
||||
aria-label="{{ 'accessibility.close' | t }}"
|
||||
>
|
||||
{{ 'icon-close.svg' | inline_asset_content }}
|
||||
</button>
|
||||
|
||||
<div
|
||||
class="product-media-modal__content color-{{ section.settings.color_scheme }} gradient"
|
||||
role="document"
|
||||
aria-label="{{ 'products.modal.label' | t }}"
|
||||
tabindex="0"
|
||||
>
|
||||
{%- liquid
|
||||
if product.selected_or_first_available_variant.featured_media != null
|
||||
assign media = product.selected_or_first_available_variant.featured_media
|
||||
render 'product-media', media: media, loop: section.settings.enable_video_looping, variant_image: section.settings.hide_variants
|
||||
endif
|
||||
-%}
|
||||
|
||||
{%- for media in product.media -%}
|
||||
{%- liquid
|
||||
if section.settings.hide_variants and variant_images contains media.src or variant_images contains media.id
|
||||
assign variant_image = true
|
||||
else
|
||||
assign variant_image = false
|
||||
endif
|
||||
|
||||
unless media.id == product.selected_or_first_available_variant.featured_media.id
|
||||
render 'product-media', media: media, loop: section.settings.enable_video_looping, variant_image: variant_image
|
||||
endunless
|
||||
-%}
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
</div>
|
||||
</product-modal>
|
||||
@@ -0,0 +1,120 @@
|
||||
{% comment %}
|
||||
Renders product media
|
||||
|
||||
Accepts:
|
||||
- media: {Object} Product Media object
|
||||
- loop: {Boolean} Enable video looping (optional)
|
||||
- variant_image: {Boolean} Whether or not media is associated with a variant
|
||||
|
||||
Usage:
|
||||
{% render 'product-media',
|
||||
media: media,
|
||||
loop: section.settings.enable_video_looping,
|
||||
variant_image: true
|
||||
%}
|
||||
{% endcomment %}
|
||||
|
||||
{%- if media.media_type == 'image' -%}
|
||||
<img
|
||||
class="global-media-settings global-media-settings--no-shadow{% if variant_image %} product__media-item--variant{% endif %}"
|
||||
srcset="
|
||||
{%- if media.preview_image.width >= 550 -%}{{ media.preview_image | image_url: width: 550 }} 550w,{%- endif -%}
|
||||
{%- if media.preview_image.width >= 1100 -%}{{ media.preview_image | image_url: width: 1100 }} 1100w,{%- endif -%}
|
||||
{%- if media.preview_image.width >= 1445 -%}{{ media.preview_image | image_url: width: 1445 }} 1445w,{%- endif -%}
|
||||
{%- if media.preview_image.width >= 1680 -%}{{ media.preview_image | image_url: width: 1680 }} 1680w,{%- endif -%}
|
||||
{%- if media.preview_image.width >= 2048 -%}{{ media.preview_image | image_url: width: 2048 }} 2048w,{%- endif -%}
|
||||
{%- if media.preview_image.width >= 2200 -%}{{ media.preview_image | image_url: width: 2200 }} 2200w,{%- endif -%}
|
||||
{%- if media.preview_image.width >= 2890 -%}{{ media.preview_image | image_url: width: 2890 }} 2890w,{%- endif -%}
|
||||
{%- if media.preview_image.width >= 4096 -%}{{ media.preview_image | image_url: width: 4096 }} 4096w,{%- endif -%}
|
||||
{{ media.preview_image | image_url }} {{ media.preview_image.width }}w
|
||||
"
|
||||
sizes="(min-width: 750px) calc(100vw - 22rem), 1100px"
|
||||
src="{{ media.preview_image | image_url: width: 1445 }}"
|
||||
alt="{{ media.alt | escape }}"
|
||||
loading="lazy"
|
||||
width="1100"
|
||||
height="{{ 1100 | divided_by: media.preview_image.aspect_ratio | ceil }}"
|
||||
data-media-id="{{ media.id }}"
|
||||
>
|
||||
{%- else -%}
|
||||
{%- if media.media_type == 'model' -%}
|
||||
<div class="product-media-modal__model" data-media-id="{{ media.id }}">
|
||||
<product-model
|
||||
class="deferred-media media media--transparent global-media-settings global-media-settings--no-shadow"
|
||||
style="padding-top: min(calc(100vh - 12rem), 100%)"
|
||||
>
|
||||
{%- else -%}
|
||||
<deferred-media
|
||||
class="deferred-media media global-media-settings global-media-settings--no-shadow"
|
||||
style="padding-top: min(calc(100vh - 12rem), {{ 1 | divided_by: media.aspect_ratio | times: 100 }}%)"
|
||||
data-media-id="{{ media.id }}"
|
||||
>
|
||||
{%- endif -%}
|
||||
|
||||
<button id="Deferred-Poster-Modal-{{ media.id }}" class="deferred-media__poster" type="button">
|
||||
<span class="deferred-media__poster-button motion-reduce">
|
||||
{%- if media.media_type == 'model' -%}
|
||||
<span class="svg-wrapper">{{ 'icon-3d-model' | inline_asset_content }}</span>
|
||||
{%- else -%}
|
||||
<span class="svg-wrapper">{{ 'icon-play.svg' | inline_asset_content }}</span>
|
||||
{%- endif -%}
|
||||
</span>
|
||||
<img
|
||||
srcset="
|
||||
{% if media.preview_image.width >= 288 %}{{ media.preview_image | image_url: width: 288 }} 288w,{% endif %}
|
||||
{% if media.preview_image.width >= 576 %}{{ media.preview_image | image_url: width: 576 }} 576w,{% endif %}
|
||||
{% if media.preview_image.width >= 550 %}{{ media.preview_image | image_url: width: 550 }} 550w,{% endif %}
|
||||
{% if media.preview_image.width >= 1100 %}{{ media.preview_image | image_url: width: 1100 }} 1100w,{% endif %}
|
||||
{{ media.preview_image | image_url }} {{ media.preview_image.width }}w
|
||||
"
|
||||
src="{{ media | image_url: width: 550, height: 550 }}"
|
||||
sizes="(min-width: 1200px) calc((1200px - 10rem) / 2), (min-width: 750px) calc((100vw - 11.5rem) / 2), calc(100vw - 4rem)"
|
||||
loading="lazy"
|
||||
width="576"
|
||||
height="{{ 576 | divided_by: media.preview_image.aspect_ratio }}"
|
||||
alt="{{ media.preview_image.alt | escape }}"
|
||||
>
|
||||
</button>
|
||||
<template>
|
||||
{%- case media.media_type -%}
|
||||
{%- when 'external_video' -%}
|
||||
{%- assign video_class = 'js-' | append: media.host -%}
|
||||
{%- if media.host == 'youtube' -%}
|
||||
{{
|
||||
media
|
||||
| external_video_url: autoplay: true, loop: loop, playlist: media.external_id
|
||||
| external_video_tag: class: video_class, loading: 'lazy'
|
||||
}}
|
||||
{%- else -%}
|
||||
{{
|
||||
media
|
||||
| external_video_url: autoplay: true, loop: loop
|
||||
| external_video_tag: class: video_class, loading: 'lazy'
|
||||
}}
|
||||
{%- endif -%}
|
||||
{%- when 'video' -%}
|
||||
{{ media | media_tag: image_size: '2048x', autoplay: true, loop: loop, controls: true, preload: 'none' }}
|
||||
{%- when 'model' -%}
|
||||
{{ media | media_tag: image_size: '2048x', toggleable: true }}
|
||||
{%- endcase -%}
|
||||
</template>
|
||||
|
||||
{%- if media.media_type == 'model' -%}
|
||||
</product-model>
|
||||
<button
|
||||
class="button button--full-width product__xr-button"
|
||||
type="button"
|
||||
aria-label="{{ 'products.product.xr_button_label' | t }}"
|
||||
data-shopify-xr
|
||||
data-shopify-model3d-id="{{ media.id }}"
|
||||
data-shopify-title="title"
|
||||
data-shopify-xr-hidden
|
||||
>
|
||||
<span class="svg-wrapper">{{ 'icon-3d-model' | inline_asset_content }}</span>
|
||||
{{ 'products.product.xr_button' | t }}
|
||||
</button>
|
||||
</div>
|
||||
{%- else -%}
|
||||
</deferred-media>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
@@ -0,0 +1,172 @@
|
||||
{% comment %}theme-check-disable ImgLazyLoading{% endcomment %}
|
||||
{% comment %}
|
||||
Renders a product thumbnail with a modal-opener
|
||||
|
||||
Accepts:
|
||||
- media: {Object} Product Media object
|
||||
- media_count: {Number} Number of media objects
|
||||
- position: {String} Position of the media. Used for accessible label.
|
||||
- desktop_layout: {String} Layout of the media for desktop.
|
||||
- mobile_layout: {String} Layout of the media for mobile.
|
||||
- loop: {Boolean} Enable video looping (optional)
|
||||
- modal_id: {String} The product modal that will be shown by clicking the thumbnail
|
||||
- xr_button: {Boolean} Renders the "View in your space" button (shopify-xr-button) if the media is a 3D Model
|
||||
- constrain_to_viewport: {Boolean} Force media height to fit within viewport
|
||||
- media_fit: {String} Method ("contain" or "cover") to fit image into container
|
||||
- media_width: {Float} The width percentage that the media column occupies on desktop.
|
||||
- lazy_load: {Boolean} Image should be lazy loaded. Default: true (optional)
|
||||
|
||||
Usage:
|
||||
{% render 'product-thumbnail',
|
||||
media: media,
|
||||
position: forloop.index,
|
||||
loop: section.settings.enable_video_looping,
|
||||
modal_id: section.id
|
||||
%}
|
||||
{% endcomment %}
|
||||
|
||||
{%- liquid
|
||||
unless lazy_load == false
|
||||
assign lazy = 'lazy'
|
||||
endunless
|
||||
|
||||
assign desktop_columns = 1
|
||||
if desktop_layout == 'columns' and media_count > 1
|
||||
assign desktop_columns = 2
|
||||
endif
|
||||
|
||||
assign mobile_columns = 1
|
||||
if mobile_layout == 'columns' and media_count > 1
|
||||
assign mobile_columns = 2
|
||||
endif
|
||||
|
||||
if media.media_type == 'image'
|
||||
assign image_class = 'image-magnify-' | append: section.settings.image_zoom
|
||||
endif
|
||||
-%}
|
||||
|
||||
{%- capture sizes -%}
|
||||
(min-width: {{ settings.page_width }}px) {{ settings.page_width | minus: 100 | times: media_width | divided_by: desktop_columns | round }}px, (min-width: 990px) calc({{ media_width | times: 100 | divided_by: desktop_columns }}vw - 10rem), (min-width: 750px) calc((100vw - 11.5rem) / 2), calc(100vw / {{ mobile_columns }} - 4rem)
|
||||
{%- endcapture -%}
|
||||
|
||||
<div
|
||||
class="product-media-container media-type-{{ media.media_type }} media-fit-{{ media_fit }} global-media-settings gradient{% if constrain_to_viewport %} constrain-height{% endif %}"
|
||||
style="--ratio: {{ media.aspect_ratio | default: 1.0 }}; --preview-ratio: {{ media.preview_image.aspect_ratio | default: 1.0 }};"
|
||||
>
|
||||
<modal-opener
|
||||
class="product__modal-opener product__modal-opener--{{ media.media_type }}"
|
||||
data-modal="#ProductModal-{{ modal_id }}"
|
||||
>
|
||||
<span
|
||||
class="product__media-icon motion-reduce quick-add-hidden{% if media.media_type == 'image' %} product__media-icon--{{ section.settings.image_zoom }}{% endif %}"
|
||||
aria-hidden="true"
|
||||
>
|
||||
{% case media.media_type %}
|
||||
{% when 'video', 'external_video' %}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-play.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{% when 'model' %}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-3d-model.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-zoom.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{% endcase %}
|
||||
</span>
|
||||
{%- render 'loading-spinner' -%}
|
||||
<div class="product__media media media--transparent">
|
||||
{{
|
||||
media.preview_image
|
||||
| image_url: width: 1946
|
||||
| image_tag:
|
||||
class: image_class,
|
||||
loading: lazy,
|
||||
sizes: sizes,
|
||||
widths: '246, 493, 600, 713, 823, 990, 1100, 1206, 1346, 1426, 1646, 1946'
|
||||
}}
|
||||
</div>
|
||||
<button
|
||||
class="product__media-toggle quick-add-hidden product__media-zoom-{{ section.settings.image_zoom }}"
|
||||
type="button"
|
||||
aria-haspopup="dialog"
|
||||
data-media-id="{{ media.id }}"
|
||||
>
|
||||
<span class="visually-hidden">
|
||||
{{ 'products.product.media.open_media' | t: index: position }}
|
||||
</span>
|
||||
</button>
|
||||
</modal-opener>
|
||||
|
||||
{%- if media.media_type != 'image' -%}
|
||||
{%- if media.media_type == 'model' -%}
|
||||
<product-model class="deferred-media media media--transparent" data-media-id="{{ media.id }}">
|
||||
{%- else -%}
|
||||
<deferred-media class="deferred-media media media--transparent" data-media-id="{{ media.id }}">
|
||||
{%- endif -%}
|
||||
<button id="Deferred-Poster-Modal-{{ media.id }}" class="deferred-media__poster" type="button">
|
||||
<span class="deferred-media__poster-button motion-reduce">
|
||||
{%- if media.media_type == 'model' -%}
|
||||
<span class="visually-hidden">{{ 'products.product.media.play_model' | t }}</span>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-3d-model.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{%- else -%}
|
||||
<span class="visually-hidden">{{ 'products.product.media.play_video' | t }}</span>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-play.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</span>
|
||||
{{
|
||||
media.preview_image
|
||||
| image_url: width: 1946
|
||||
| image_tag:
|
||||
loading: lazy,
|
||||
sizes: sizes,
|
||||
widths: '246, 493, 600, 713, 823, 990, 1100, 1206, 1346, 1426, 1646, 1946'
|
||||
}}
|
||||
</button>
|
||||
<template>
|
||||
{%- liquid
|
||||
case media.media_type
|
||||
when 'external_video'
|
||||
assign video_class = 'js-' | append: media.host
|
||||
if media.host == 'youtube'
|
||||
echo media | external_video_url: autoplay: true, loop: loop, playlist: media.external_id | external_video_tag: class: video_class, loading: 'lazy'
|
||||
else
|
||||
echo media | external_video_url: autoplay: true, loop: loop | external_video_tag: class: video_class, loading: 'lazy'
|
||||
endif
|
||||
when 'video'
|
||||
echo media | media_tag: image_size: '2048x', autoplay: true, loop: loop, controls: true, preload: 'none'
|
||||
when 'model'
|
||||
echo media | media_tag: image_size: '2048x', toggleable: true
|
||||
endcase
|
||||
-%}
|
||||
</template>
|
||||
|
||||
{%- if media.media_type == 'model' -%}
|
||||
</product-model>
|
||||
{%- if xr_button -%}
|
||||
<button
|
||||
class="button button--full-width product__xr-button"
|
||||
type="button"
|
||||
aria-label="{{ 'products.product.xr_button_label' | t }}"
|
||||
data-shopify-xr
|
||||
data-shopify-model3d-id="{{ media.id }}"
|
||||
data-shopify-title="{{ product.title | escape }}"
|
||||
data-shopify-xr-hidden
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-3d-model.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
{{ 'products.product.xr_button' | t }}
|
||||
</button>
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
</deferred-media>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
@@ -0,0 +1,124 @@
|
||||
{% comment %}
|
||||
Renders product variant options
|
||||
|
||||
Accepts:
|
||||
- product: {Object} product object.
|
||||
- option: {Object} current product_option object.
|
||||
- block: {Object} block object.
|
||||
- picker_type: {String} type of picker to dispay
|
||||
|
||||
|
||||
Usage:
|
||||
{% render 'product-variant-options',
|
||||
product: product,
|
||||
option: option,
|
||||
block: block
|
||||
picker_type: picker_type
|
||||
%}
|
||||
{% endcomment %}
|
||||
{%- liquid
|
||||
assign product_form_id = 'product-form-' | append: section.id
|
||||
-%}
|
||||
|
||||
{%- for value in option.values -%}
|
||||
{%- liquid
|
||||
assign swatch_focal_point = null
|
||||
if value.swatch.image
|
||||
assign image_url = value.swatch.image | image_url: width: 50
|
||||
assign swatch_value = 'url(' | append: image_url | append: ')'
|
||||
assign swatch_focal_point = value.swatch.image.presentation.focal_point
|
||||
elsif value.swatch.color
|
||||
assign swatch_value = 'rgb(' | append: value.swatch.color.rgb | append: ')'
|
||||
else
|
||||
assign swatch_value = null
|
||||
endif
|
||||
|
||||
assign option_disabled = true
|
||||
if value.available
|
||||
assign option_disabled = false
|
||||
endif
|
||||
-%}
|
||||
|
||||
{%- capture input_id -%}
|
||||
{{ section.id }}-{{ option.position }}-{{ forloop.index0 -}}
|
||||
{%- endcapture -%}
|
||||
|
||||
{%- capture input_name -%}
|
||||
{{ option.name }}-{{ option.position }}
|
||||
{%- endcapture -%}
|
||||
|
||||
{%- capture input_dataset -%}
|
||||
data-product-url="{{ value.product_url }}"
|
||||
data-option-value-id="{{ value.id }}"
|
||||
data-option-name="{{ option.name | escape }}"
|
||||
{%- endcapture -%}
|
||||
|
||||
{%- capture label_unavailable -%}
|
||||
<span class="visually-hidden label-unavailable">
|
||||
{{- 'products.product.variant_sold_out_or_unavailable' | t -}}
|
||||
</span>
|
||||
{%- endcapture -%}
|
||||
|
||||
{% assign escaped_value = value | escape %}
|
||||
|
||||
{%- if picker_type == 'swatch' -%}
|
||||
{%- capture help_text -%}
|
||||
<span class="visually-hidden">{{ escaped_value }}</span>
|
||||
{{ label_unavailable }}
|
||||
{%- endcapture -%}
|
||||
|
||||
{%
|
||||
render 'swatch-input',
|
||||
id: input_id,
|
||||
name: input_name,
|
||||
value: escaped_value,
|
||||
swatch: value.swatch,
|
||||
product_form_id: product_form_id,
|
||||
checked: value.selected,
|
||||
visually_disabled: option_disabled,
|
||||
shape: block.settings.swatch_shape,
|
||||
help_text: help_text,
|
||||
additional_props: input_dataset
|
||||
%}
|
||||
{%- elsif picker_type == 'button' -%}
|
||||
<input
|
||||
type="radio"
|
||||
id="{{ input_id }}"
|
||||
name="{{ input_name | escape }}"
|
||||
value="{{ escaped_value }}"
|
||||
form="{{ product_form_id }}"
|
||||
{% if value.selected %}
|
||||
checked
|
||||
{% endif %}
|
||||
{% if option_disabled %}
|
||||
class="disabled"
|
||||
{% endif %}
|
||||
{{ input_dataset }}
|
||||
>
|
||||
<label for="{{ input_id }}">
|
||||
{{ value -}}
|
||||
{{ label_unavailable }}
|
||||
</label>
|
||||
{%- elsif picker_type == 'dropdown' or picker_type == 'swatch_dropdown' -%}
|
||||
<option
|
||||
id="{{ input_id }}"
|
||||
value="{{ escaped_value }}"
|
||||
{% if value.selected %}
|
||||
selected="selected"
|
||||
{% endif %}
|
||||
{% if swatch_value and picker_type == 'swatch_dropdown' %}
|
||||
data-option-swatch-value="{{ swatch_value }}"
|
||||
{% if swatch_focal_point %}
|
||||
data-option-swatch-focal-point="{{ swatch_focal_point }}"
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{{ input_dataset }}
|
||||
>
|
||||
{% if option_disabled -%}
|
||||
{{- 'products.product.value_unavailable' | t: option_value: value -}}
|
||||
{%- else -%}
|
||||
{{- value -}}
|
||||
{%- endif %}
|
||||
</option>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
@@ -0,0 +1,101 @@
|
||||
{% comment %}
|
||||
Renders product variant-picker
|
||||
|
||||
Accepts:
|
||||
- product: {Object} product object.
|
||||
- block: {Object} passing the block information.
|
||||
- product_form_id: {String} Id of the product form to which the variant picker is associated.
|
||||
Usage:
|
||||
{% render 'product-variant-picker', product: product, block: block, product_form_id: product_form_id %}
|
||||
{% endcomment %}
|
||||
{%- unless product.has_only_default_variant -%}
|
||||
<variant-selects
|
||||
id="variant-selects-{{ section.id }}"
|
||||
data-section="{{ section.id }}"
|
||||
data-product-handle="{{ product.handle }}"
|
||||
data-product-title="{{ product.title | escape }}"
|
||||
data-product-id="{{ product.id }}"
|
||||
data-currency-code="{{ cart.currency.iso_code }}"
|
||||
{% # theme-check-disable %}
|
||||
data-selected-price-amount="{{ product.selected_or_first_available_variant.price | default: 0 | money_amount | escape }}"
|
||||
{% # theme-check-enable %}
|
||||
{{ block.shopify_attributes }}
|
||||
>
|
||||
{%- for option in product.options_with_values -%}
|
||||
{%- liquid
|
||||
assign swatch_count = option.values | map: 'swatch' | compact | size
|
||||
assign picker_type = block.settings.picker_type
|
||||
|
||||
if swatch_count > 0 and block.settings.swatch_shape != 'none'
|
||||
if block.settings.picker_type == 'dropdown'
|
||||
assign picker_type = 'swatch_dropdown'
|
||||
else
|
||||
assign picker_type = 'swatch'
|
||||
endif
|
||||
endif
|
||||
-%}
|
||||
{%- if picker_type == 'swatch' -%}
|
||||
<fieldset class="js product-form__input product-form__input--swatch">
|
||||
<legend class="form__label">
|
||||
{{ option.name }}:
|
||||
<span data-selected-value>
|
||||
{{- option.selected_value -}}
|
||||
</span>
|
||||
</legend>
|
||||
{% render 'product-variant-options',
|
||||
product: product,
|
||||
option: option,
|
||||
block: block,
|
||||
picker_type: picker_type
|
||||
%}
|
||||
</fieldset>
|
||||
{%- elsif picker_type == 'button' -%}
|
||||
<fieldset class="js product-form__input product-form__input--pill">
|
||||
<legend class="form__label">{{ option.name }}</legend>
|
||||
{% render 'product-variant-options',
|
||||
product: product,
|
||||
option: option,
|
||||
block: block,
|
||||
picker_type: picker_type
|
||||
%}
|
||||
</fieldset>
|
||||
{%- else -%}
|
||||
<div class="product-form__input product-form__input--dropdown">
|
||||
<label class="form__label" for="Option-{{ section.id }}-{{ forloop.index0 }}">
|
||||
{{ option.name }}
|
||||
</label>
|
||||
<div class="select">
|
||||
{%- if picker_type == 'swatch_dropdown' -%}
|
||||
<span
|
||||
data-selected-value
|
||||
class="dropdown-swatch"
|
||||
>
|
||||
{% render 'swatch', swatch: option.selected_value.swatch, shape: block.settings.swatch_shape %}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
<select
|
||||
id="Option-{{ section.id }}-{{ forloop.index0 }}"
|
||||
class="select__select"
|
||||
name="options[{{ option.name | escape }}]"
|
||||
form="{{ product_form_id }}"
|
||||
>
|
||||
{% render 'product-variant-options',
|
||||
product: product,
|
||||
option: option,
|
||||
block: block,
|
||||
picker_type: picker_type
|
||||
%}
|
||||
</select>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-caret.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
|
||||
<script type="application/json" data-selected-variant>
|
||||
{{ product.selected_or_first_available_variant | json }}
|
||||
</script>
|
||||
</variant-selects>
|
||||
{%- endunless -%}
|
||||
@@ -0,0 +1,5 @@
|
||||
<div class="progress-bar-container hidden">
|
||||
<div class="progress-bar">
|
||||
<div class="progress-bar-value"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,47 @@
|
||||
{% comment %}
|
||||
Quantity input
|
||||
|
||||
Accepts:
|
||||
- variant: {Object} Variant object
|
||||
- variant_id: {String} Variant ID (optional)
|
||||
- min: {Number} Min (optional)
|
||||
|
||||
Usage:
|
||||
{% render 'quantity-input' variant: variant %}
|
||||
{% endcomment %}
|
||||
|
||||
<quantity-input class="quantity cart-quantity">
|
||||
<button class="quantity__button" name="minus" type="button" data-target="decrement-{{ variant.id }}">
|
||||
<span class="visually-hidden">
|
||||
{{- 'products.product.quantity.decrease' | t: product: variant.title | escape -}}
|
||||
</span>
|
||||
<span class="svg-wrapper">{{ 'icon-minus.svg' | inline_asset_content }}</span>
|
||||
</button>
|
||||
<input
|
||||
class="quantity__input"
|
||||
data-quantity-variant-id="{{ variant.id }}"
|
||||
type="number"
|
||||
name="updates[{{ variant_id }}]"
|
||||
{% # theme-check-disable %}
|
||||
value="{{ cart | item_count_for_variant: variant.id }}"
|
||||
data-cart-quantity="{{ cart | item_count_for_variant: variant.id }}"
|
||||
min="{{ min }}"
|
||||
data-min="{{ variant.quantity_rule.min }}"
|
||||
{% if variant.quantity_rule.max != null %}
|
||||
max="{{ variant.quantity_rule.max }}"
|
||||
{% endif %}
|
||||
step="{{ variant.quantity_rule.increment }}"
|
||||
{% # theme-check-enable %}
|
||||
aria-label="{{ 'products.product.quantity.input_label' | t: product: variant.title | escape }}"
|
||||
id="Quantity-{{ variant.id }}"
|
||||
data-index="{{ variant.id }}"
|
||||
data-target="quantity-input-{{ variant.id }}"
|
||||
>
|
||||
<button class="quantity__button" name="plus" type="button" data-target="increment-{{ variant.id }}">
|
||||
<span class="visually-hidden">
|
||||
{{- 'products.product.quantity.increase' | t: product: variant.title | escape -}}
|
||||
</span>
|
||||
<span class="svg-wrapper">{{ 'icon-plus.svg' | inline_asset_content }}</span>
|
||||
</button>
|
||||
{%- render 'progress-bar' -%}
|
||||
</quantity-input>
|
||||
@@ -0,0 +1,453 @@
|
||||
{% comment %}
|
||||
Variant List Row
|
||||
|
||||
Accepts:
|
||||
- item: {Object} Variant or Product object
|
||||
- sku: {String} Sku of Product or Variant (optional)
|
||||
- image: {Object} Product or Variant image (optional)
|
||||
Usage:
|
||||
{% render 'quick-order-list-row' variant: variant %}
|
||||
{% endcomment %}
|
||||
|
||||
{% # theme-check-disable %}
|
||||
{% assign cart_qty = cart | item_count_for_variant: variant.id %}
|
||||
{% # theme-check-enable %}
|
||||
|
||||
<tr
|
||||
class="variant-item{% unless show_image %} variant-item--no-media{% endunless %}{% if item.available and item.unit_price_measurement %} variant-item--unit-price{% endif %}"
|
||||
id="Variant-{{ variant.id }}"
|
||||
data-variant-id="{{ variant.id }}"
|
||||
>
|
||||
<td class="variant-item__inner{% unless sku and show_sku %} variant-item__inner--no-sku{% endunless %}">
|
||||
{%- if show_image -%}
|
||||
<div class="variant-item__media">
|
||||
<div class="variant-item__image-container global-media-settings{% unless is_modal %} gradient{% endunless %}{% unless image %} variant-item__image-container--no-img{% endunless %}">
|
||||
{% if image %}
|
||||
{%- assign img_height = 43 | divided_by: image.aspect_ratio | ceil -%}
|
||||
{{
|
||||
image
|
||||
| image_url: width: 86
|
||||
| image_tag:
|
||||
loading: 'lazy',
|
||||
fetchpriority: 'low',
|
||||
decoding: 'async',
|
||||
class: 'variant-item__image',
|
||||
width: 43,
|
||||
height: img_height,
|
||||
widths: '86',
|
||||
alt: image.alt
|
||||
| escape
|
||||
}}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<div class="small-hide medium-hide">
|
||||
<span class="variant-item__name h4 break">{{ item.title | escape }}</span>
|
||||
{%- if show_sku -%}
|
||||
<span class="variant-item__sku break">{{ sku | escape }}</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="variant-item__details large-up-hide">
|
||||
<div class="variant-item__info">
|
||||
<span class="variant-item__name h4 break">{{ item.title | escape }}</span>
|
||||
{%- if show_sku -%}
|
||||
<span class="variant-item__sku break">{{ sku | escape }}</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
|
||||
{%- assign item_price = item.price | money -%}
|
||||
{%- if item.compare_at_price -%}
|
||||
<dl class="variant-item__discounted-prices">
|
||||
<dt class="visually-hidden">
|
||||
{{ 'products.product.price.regular_price' | t }}
|
||||
</dt>
|
||||
<dd>
|
||||
<s class="variant-item__old-price price price--end">
|
||||
{{ item.compare_at_price | money }}
|
||||
</s>
|
||||
</dd>
|
||||
<dt class="visually-hidden">
|
||||
{{ 'products.product.price.sale_price' | t }}
|
||||
</dt>
|
||||
<dd class="price">
|
||||
{%- if variant.quantity_price_breaks.size > 0 -%}
|
||||
{%- liquid
|
||||
assign volume_pricing_array = variant.quantity_price_breaks | sort: 'quantity' | reverse
|
||||
-%}
|
||||
<price-per-item
|
||||
class="variant-item__price-per-item"
|
||||
id="Price-Per-Item-{{ variant.id }}"
|
||||
data-variant-id="{{ variant.id }}"
|
||||
>
|
||||
<div class="price-per-item">
|
||||
{%- if cart_qty < volume_pricing_array.last.minimum_quantity -%}
|
||||
{%- assign variant_price = variant.price | money -%}
|
||||
<span class="price-per-item--current price">
|
||||
{{- 'sections.quick_order_list.each' | t: money: variant_price -}}
|
||||
</span>
|
||||
{%- else -%}
|
||||
{%- for price_break in volume_pricing_array -%}
|
||||
{%- if cart_qty >= price_break.minimum_quantity -%}
|
||||
{%- assign price_break_price = price_break.price | money -%}
|
||||
<span class="price-per-item--current price">
|
||||
{{- 'sections.quick_order_list.each' | t: money: price_break_price -}}
|
||||
</span>
|
||||
{%- break -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</price-per-item>
|
||||
{%- else -%}
|
||||
<span class="price">
|
||||
{{- 'sections.quick_order_list.each' | t: money: item_price -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</dd>
|
||||
</dl>
|
||||
{%- else -%}
|
||||
{%- if variant.quantity_price_breaks.size > 0 -%}
|
||||
{%- liquid
|
||||
assign volume_pricing_array = variant.quantity_price_breaks | sort: 'quantity' | reverse
|
||||
-%}
|
||||
<price-per-item
|
||||
class="variant-item__price-per-item"
|
||||
id="Price-Per-Item-{{ variant.id }}"
|
||||
data-variant-id="{{ variant.id }}"
|
||||
>
|
||||
<div class="price-per-item">
|
||||
{%- if cart_qty < volume_pricing_array.last.minimum_quantity -%}
|
||||
{%- assign variant_price = variant.price | money -%}
|
||||
<span class="price-per-item--current price">
|
||||
{{- 'sections.quick_order_list.each' | t: money: variant_price -}}
|
||||
</span>
|
||||
{%- else -%}
|
||||
{%- for price_break in volume_pricing_array -%}
|
||||
{%- if cart_qty >= price_break.minimum_quantity -%}
|
||||
{%- assign price_break_price = price_break.price | money -%}
|
||||
<span class="price-per-item--current price">
|
||||
{{- 'sections.quick_order_list.each' | t: money: price_break_price -}}
|
||||
</span>
|
||||
{%- break -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</price-per-item>
|
||||
{%- else -%}
|
||||
<span class="price">
|
||||
{{- 'sections.quick_order_list.each' | t: money: item_price -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
{%- if item.available and item.unit_price_measurement -%}
|
||||
{% render 'unit-price', price: item.unit_price, measurement: item.unit_price_measurement %}
|
||||
{%- endif -%}
|
||||
</td>
|
||||
|
||||
<td class="variant-item__totals right large-up-hide">
|
||||
{%- render 'loading-spinner' -%}
|
||||
{% comment %} TODO: enable theme-check once `line_items_for` is accepted as valid filter {% endcomment %}
|
||||
{% # theme-check-disable %}
|
||||
<span class="price">{{ cart | line_items_for: item | sum: 'original_line_price' | money }}</span>
|
||||
{% # theme-check-enable %}
|
||||
</td>
|
||||
|
||||
<td class="variant-item__quantity">
|
||||
{%- liquid
|
||||
assign check_against_inventory = true
|
||||
if variant.inventory_management != 'shopify' or variant.inventory_policy == 'continue'
|
||||
assign check_against_inventory = false
|
||||
endif
|
||||
if variant.quantity_rule.min > variant.inventory_quantity and check_against_inventory
|
||||
assign quantity_rule_soldout = true
|
||||
endif
|
||||
|
||||
assign has_qty_rules = false
|
||||
if variant.quantity_rule.increment > 1 or variant.quantity_rule.min > 1 or variant.quantity_rule.max != null
|
||||
assign has_qty_rules = true
|
||||
endif
|
||||
|
||||
assign has_vol_pricing = false
|
||||
if variant.quantity_price_breaks.size > 0
|
||||
assign has_vol_pricing = true
|
||||
endif
|
||||
|
||||
assign is_available = false
|
||||
assign has_popover = false
|
||||
unless variant.available == false or quantity_rule_soldout
|
||||
assign is_available = true
|
||||
endunless
|
||||
if has_qty_rules or has_vol_pricing
|
||||
assign has_popover = true
|
||||
endif
|
||||
-%}
|
||||
<quantity-popover>
|
||||
<div class="variant-item__quantity-wrapper quantity-popover-wrapper{% unless has_popover %} variant-item__quantity-wrapper--no-info{% endunless %}">
|
||||
<label class="visually-hidden" for="Quantity-{{ variant.id }}">
|
||||
{{ 'products.product.quantity.label' | t }}
|
||||
</label>
|
||||
<div class="quantity-popover-container{% if is_available and has_popover %} quantity-popover-container--hover{% endif %}{% if cart_qty == 0 %} quantity-popover-container--empty{% endif %}">
|
||||
{%- if has_qty_rules or has_vol_pricing -%}
|
||||
<button
|
||||
type="button"
|
||||
aria-expanded="false"
|
||||
aria-controls="quantity-popover-info-{{ variant.id }}"
|
||||
aria-label="
|
||||
{%- if has_vol_pricing -%}
|
||||
{{ 'products.product.volume_pricing.note' | t }}
|
||||
{%- elsif has_qty_rules -%}
|
||||
{{ 'products.product.quantity.note' | t }}
|
||||
{%- endif -%}
|
||||
"
|
||||
class="quantity-popover__info-button quantity-popover__info-button--icon-only button button--tertiary small-hide medium-hide no-js-hidden"
|
||||
>
|
||||
{{- 'icon-info.svg' | inline_asset_content -}}
|
||||
</button>
|
||||
<div
|
||||
class="global-settings-popup quantity-popover__info"
|
||||
tabindex="-1"
|
||||
hidden
|
||||
id="quantity-popover-info-{{ variant.id }}"
|
||||
>
|
||||
{%- if has_qty_rules == false -%}
|
||||
<span class="volume-pricing-label caption">{{ 'products.product.volume_pricing.title' | t }}</span>
|
||||
{%- endif -%}
|
||||
<div class="quantity__rules caption no-js-hidden">
|
||||
{%- if variant.quantity_rule.increment > 1 -%}
|
||||
<span class="divider">
|
||||
{{- 'products.product.quantity.multiples_of' | t: quantity: variant.quantity_rule.increment -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- if variant.quantity_rule.min > 1 -%}
|
||||
<span class="divider">
|
||||
{{- 'products.product.quantity.min_of' | t: quantity: variant.quantity_rule.min -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- if variant.quantity_rule.max != null -%}
|
||||
<span class="divider">
|
||||
{{- 'products.product.quantity.max_of' | t: quantity: variant.quantity_rule.max -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
<button
|
||||
class="button-close button button--tertiary large-up-hide"
|
||||
type="button"
|
||||
aria-label="{{ 'accessibility.close' | t }}"
|
||||
>
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</button>
|
||||
{%- if variant.quantity_price_breaks.size > 0 -%}
|
||||
<volume-pricing class="parent-display">
|
||||
<ul class="list-unstyled">
|
||||
<li>
|
||||
<span>{{ variant.quantity_rule.min }}+</span>
|
||||
{%- assign price = variant.price | money_with_currency -%}
|
||||
<span>{{ 'sections.quick_order_list.each' | t: money: price }}</span>
|
||||
</li>
|
||||
{%- for price_break in variant.quantity_price_breaks -%}
|
||||
<li>
|
||||
<span>
|
||||
{{- price_break.minimum_quantity -}}
|
||||
<span aria-hidden="true">+</span></span
|
||||
>
|
||||
{%- assign price = price_break.price | money_with_currency -%}
|
||||
<span> {{ 'sections.quick_order_list.each' | t: money: price }}</span>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</volume-pricing>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if variant.available == false or quantity_rule_soldout -%}
|
||||
<span class="variant-item__sold-out"> {{ 'products.product.sold_out' | t }} </span>
|
||||
{%- else -%}
|
||||
{% comment %} TODO: Remove theme check {% endcomment %}
|
||||
{% # theme-check-disable %}
|
||||
{% assign cart_qty = cart | item_count_for_variant: variant.id %}
|
||||
{% # theme-check-enable %}
|
||||
{% render 'quantity-input', variant: variant, min: 0 %}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{% if cart_qty > 0 %}
|
||||
<div
|
||||
id="Remove-{{ variant.id }}"
|
||||
class="quick-order-list-remove-button"
|
||||
data-index="{{ variant.id }}"
|
||||
>
|
||||
<button
|
||||
class="button button--tertiary"
|
||||
aria-label="{{ 'sections.cart.remove_title' | t: title: item.title }}"
|
||||
data-target="remove-{{ variant.id }}"
|
||||
>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-remove.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{%- if has_popover -%}
|
||||
<button
|
||||
type="button"
|
||||
class="quantity-popover__info-button quantity-popover__info-button--icon-with-label button button--tertiary large-up-hide"
|
||||
aria-expanded="false"
|
||||
>
|
||||
{{- 'icon-info.svg' | inline_asset_content -}}
|
||||
<span>
|
||||
{%- if has_vol_pricing -%}
|
||||
{{ 'products.product.volume_pricing.note' | t }}
|
||||
{%- elsif has_qty_rules -%}
|
||||
{{ 'products.product.quantity.note' | t }}
|
||||
{%- endif -%}
|
||||
</span>
|
||||
</button>
|
||||
{%- endif -%}
|
||||
<div
|
||||
class="variant-item__error large-up-hide"
|
||||
id="Quick-order-list-item-error-mobile-{{ variant.id }}"
|
||||
role="alert"
|
||||
>
|
||||
<small class="variant-item__error-text"></small>
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-error.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</div>
|
||||
</quantity-popover>
|
||||
</td>
|
||||
{%- assign item_price = item.price | money -%}
|
||||
<td class="variant-item__price small-hide medium-hide">
|
||||
{%- if item.compare_at_price -%}
|
||||
<dl class="variant-item__discounted-prices">
|
||||
<dt class="visually-hidden">
|
||||
{{ 'products.product.price.regular_price' | t }}
|
||||
</dt>
|
||||
<dd>
|
||||
<s class="variant-item__old-price price price--end">
|
||||
{{ item.compare_at_price | money }}
|
||||
</s>
|
||||
</dd>
|
||||
<dt class="visually-hidden">
|
||||
{{ 'products.product.price.sale_price' | t }}
|
||||
</dt>
|
||||
<dd class="price">
|
||||
{%- if variant.quantity_price_breaks.size > 0 -%}
|
||||
{%- liquid
|
||||
assign volume_pricing_array = variant.quantity_price_breaks | sort: 'quantity' | reverse
|
||||
-%}
|
||||
<price-per-item
|
||||
class="variant-item__price-per-item"
|
||||
id="Price-Per-Item-{{ variant.id }}"
|
||||
data-variant-id="{{ variant.id }}"
|
||||
>
|
||||
<div class="price-per-item">
|
||||
{%- if cart_qty < volume_pricing_array.last.minimum_quantity -%}
|
||||
{%- assign variant_price = variant.price | money -%}
|
||||
<span class="price-per-item--current price">
|
||||
{{- 'sections.quick_order_list.each' | t: money: variant_price -}}
|
||||
</span>
|
||||
{%- else -%}
|
||||
{%- for price_break in volume_pricing_array -%}
|
||||
{%- if cart_qty >= price_break.minimum_quantity -%}
|
||||
{%- assign price_break_price = price_break.price | money -%}
|
||||
<span class="price-per-item--current price">
|
||||
{{- 'sections.quick_order_list.each' | t: money: price_break_price -}}
|
||||
</span>
|
||||
{%- break -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</price-per-item>
|
||||
{%- else -%}
|
||||
<span class="price">
|
||||
{{- 'sections.quick_order_list.each' | t: money: item_price -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
</dd>
|
||||
</dl>
|
||||
{%- else -%}
|
||||
{%- if variant.quantity_price_breaks.size > 0 -%}
|
||||
{%- liquid
|
||||
assign volume_pricing_array = variant.quantity_price_breaks | sort: 'quantity' | reverse
|
||||
-%}
|
||||
<price-per-item
|
||||
class="variant-item__price-per-item"
|
||||
id="Price-Per-Item-{{ variant.id }}"
|
||||
data-variant-id="{{ variant.id }}"
|
||||
>
|
||||
<div class="price-per-item">
|
||||
{%- if cart_qty < volume_pricing_array.last.minimum_quantity -%}
|
||||
{%- assign variant_price = variant.price | money -%}
|
||||
<span class="price-per-item--current price">
|
||||
{{- 'sections.quick_order_list.each' | t: money: variant_price -}}
|
||||
</span>
|
||||
{%- else -%}
|
||||
{%- for price_break in volume_pricing_array -%}
|
||||
{%- if cart_qty >= price_break.minimum_quantity -%}
|
||||
{%- assign price_break_price = price_break.price | money -%}
|
||||
<span class="price-per-item--current price">
|
||||
{{- 'sections.quick_order_list.each' | t: money: price_break_price -}}
|
||||
</span>
|
||||
{%- break -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
</div>
|
||||
</price-per-item>
|
||||
{%- else -%}
|
||||
<span class="price">
|
||||
{{- 'sections.quick_order_list.each' | t: money: item_price -}}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
{%- if item.available and item.unit_price_measurement -%}
|
||||
{% render 'unit-price', price: item.unit_price, measurement: item.unit_price_measurement %}
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td class="variant-item__totals right small-hide medium-hide">
|
||||
{%- render 'loading-spinner' -%}
|
||||
{% comment %} TODO: enable theme-check once `line_items_for` is accepted as valid filter {% endcomment %}
|
||||
{% # theme-check-disable %}
|
||||
<span class="price">{{ cart | line_items_for: item | sum: 'original_line_price' | money }}</span>
|
||||
{% # theme-check-enable %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="small-hide medium-hide hidden desktop-row-error">
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="variant-item__error" id="Quick-order-list-item-error-desktop-{{ variant.id }}" role="alert">
|
||||
<small class="variant-item__error-text"></small>
|
||||
<span class="svg-wrapper">{{ 'icon-error.svg' | inline_asset_content }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
{%- if product.quantity_price_breaks_configured? -%}
|
||||
<volume-pricing class="hidden" id="Volume-{{ variant.id }}">
|
||||
<ul>
|
||||
<li>
|
||||
<span>{{ variant.quantity_rule.min }}</span>
|
||||
{%- assign price = variant.price | money -%}
|
||||
<span data-text="{{ price }}">{{ price }}</span>
|
||||
</li>
|
||||
{%- for price_break in variant.quantity_price_breaks -%}
|
||||
{%- assign price_break_price = price_break.price | money -%}
|
||||
<li>
|
||||
<span>
|
||||
{{- price_break.minimum_quantity -}}
|
||||
</span>
|
||||
<span data-text="{{ price_break_price }}">{{- price_break.price | money }}</span>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</volume-pricing>
|
||||
{%- endif -%}
|
||||
@@ -0,0 +1,300 @@
|
||||
{% comment %}
|
||||
Renders a list of product's variants
|
||||
|
||||
Accepts:
|
||||
- product: {Object} Product Liquid object
|
||||
- show_image: {Boolean} Shows image of the variant in the row
|
||||
- is_modal: {Boolean} Defines if this snippet lives in a modal (optional)
|
||||
|
||||
Usage:
|
||||
{% render 'quick-order-list', product: product %}
|
||||
{% endcomment %}
|
||||
|
||||
{% comment %} TODO: enable theme-check once `line_items_for` is accepted as valid filter {% endcomment %}
|
||||
{% # theme-check-disable %}
|
||||
{%- assign items_in_cart = cart | line_items_for: product | sum: 'quantity' -%}
|
||||
{% # theme-check-enable %}
|
||||
<div class="quick-order-list-container color-{{ section.settings.color_scheme }}{% unless is_modal %} gradient{% endunless %}">
|
||||
<quick-order-list
|
||||
class="page-width section-{{ section.id }}-padding"
|
||||
id="{{ section.id }}-{{ product.id }}"
|
||||
data-section="{{ section.id }}"
|
||||
data-product-id="{{ product.id }}"
|
||||
data-url="{{ product.url }}"
|
||||
>
|
||||
<form
|
||||
action="{{ routes.cart_update_url }}"
|
||||
class="quick-order-list__contents critical-hidden"
|
||||
method="post"
|
||||
id="QuickOrderList"
|
||||
>
|
||||
{% paginate product.variants by section.settings.variants_per_page %}
|
||||
<div class="quick-order-list__container" id="main-variant-items">
|
||||
<table class="quick-order-list__table">
|
||||
<caption class="visually-hidden">
|
||||
{{ 'sections.cart.title' | t }}
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="caption-with-letter-spacing" scope="col">
|
||||
{%- if product.has_only_default_variant -%}
|
||||
{{ 'sections.quick_order_list.product' | t }}
|
||||
{%- else -%}
|
||||
{{ 'sections.quick_order_list.variant' | t }}
|
||||
{%- endif -%}
|
||||
</th>
|
||||
<th class="large-up-hide right caption-with-letter-spacing" scope="col">
|
||||
{%- if product.has_only_default_variant -%}
|
||||
{{ 'sections.quick_order_list.product_total' | t }}
|
||||
{%- else -%}
|
||||
{{ 'sections.quick_order_list.variant_total' | t }}
|
||||
{%- endif -%}
|
||||
</th>
|
||||
<th
|
||||
class="quick-order-list__table-heading--wide small-hide medium-hide caption-with-letter-spacing"
|
||||
scope="col"
|
||||
>
|
||||
{{ 'products.product.quantity.label' | t }}
|
||||
</th>
|
||||
<th
|
||||
class="quick-order-list__table-heading--wide small-hide medium-hide caption-with-letter-spacing"
|
||||
scope="col"
|
||||
>
|
||||
{{ 'sections.cart.headings.price' | t }}
|
||||
</th>
|
||||
<th class="small-hide medium-hide right caption-with-letter-spacing" scope="col">
|
||||
{%- if product.has_only_default_variant -%}
|
||||
{{ 'sections.quick_order_list.product_total' | t }}
|
||||
{%- else -%}
|
||||
{{ 'sections.quick_order_list.variant_total' | t }}
|
||||
{%- endif -%}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{%- if product.has_only_default_variant -%}
|
||||
{%- render 'quick-order-list-row',
|
||||
item: product,
|
||||
image: product.featured_media,
|
||||
sku: product.selected_or_first_available_variant.sku,
|
||||
variant: product.selected_or_first_available_variant,
|
||||
show_image: show_image,
|
||||
show_sku: show_sku,
|
||||
is_modal: is_modal
|
||||
-%}
|
||||
{%- else -%}
|
||||
{%- for variant in product.variants -%}
|
||||
{%- render 'quick-order-list-row',
|
||||
item: variant,
|
||||
image: variant.image,
|
||||
sku: variant.sku,
|
||||
variant: variant,
|
||||
show_image: show_image,
|
||||
show_sku: show_sku,
|
||||
is_modal: is_modal
|
||||
-%}
|
||||
{%- endfor -%}
|
||||
{%- endif -%}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="js-paginate">
|
||||
{% render 'pagination', paginate: paginate %}
|
||||
</div>
|
||||
{%- endpaginate -%}
|
||||
|
||||
<p
|
||||
class="visually-hidden"
|
||||
id="quick-order-list-live-region-text-{{ product.id }}"
|
||||
aria-live="polite"
|
||||
role="status"
|
||||
></p>
|
||||
<p
|
||||
class="visually-hidden"
|
||||
id="shopping-cart-variant-item-status"
|
||||
aria-live="polite"
|
||||
aria-hidden="true"
|
||||
role="status"
|
||||
>
|
||||
{{ 'accessibility.loading' | t }}
|
||||
</p>
|
||||
</form>
|
||||
|
||||
{%- if product.has_only_default_variant or product.variants_count == 1 -%}
|
||||
<span class="quick-order-list-error">
|
||||
{% comment %} Populated by JS {% endcomment %}
|
||||
</span>
|
||||
{%- else -%}
|
||||
<div
|
||||
class="quick-order-list__total{% unless is_modal %} gradient{% endunless %}"
|
||||
id="quick-order-list-total-{{ product.id }}-{{ section.id }}"
|
||||
>
|
||||
<div class="quick-order-list-total__info">
|
||||
<div class="quick-order-list-total__column small-hide medium-hide">
|
||||
<div class="quick-order-list-buttons">
|
||||
<a
|
||||
href="{{ routes.cart_url }} "
|
||||
class="quick-order-list__button button button--secondary small-hide medium-hide"
|
||||
>
|
||||
<span class="quick-order-list__button-text">{{- 'sections.quick_order_list.view_cart' | t -}}</span>
|
||||
</a>
|
||||
<div class="variant-remove-total{% if items_in_cart == 0 %} variant-remove-total--empty{% endif %}">
|
||||
{%- render 'loading-spinner' -%}
|
||||
<quick-order-list-remove-all-button
|
||||
data-action="confirm"
|
||||
class="{% if items_in_cart == 0 %}hidden{% endif %}"
|
||||
>
|
||||
<button class="button button--tertiary" type="button">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-remove.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="text-body">{{ 'sections.quick_order_list.remove_all' | t }}</span>
|
||||
</button>
|
||||
</quick-order-list-remove-all-button>
|
||||
</div>
|
||||
</div>
|
||||
<span class="quick-order-list__message caption-large" role="status">
|
||||
<span class="quick-order-list__message-icon hidden">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-checkmark.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</span>
|
||||
<span class="quick-order-list__message-text"></span>
|
||||
</span>
|
||||
<span class="quick-order-list-error">
|
||||
{% comment %} Populated by JS {% endcomment %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="quick-order-list__total-items">
|
||||
<span>
|
||||
{{ items_in_cart }}
|
||||
</span>
|
||||
<p class="h5">{{ 'sections.quick_order_list.total_items' | t }}</p>
|
||||
</div>
|
||||
<div class="quick-order-list-total__price">
|
||||
<div class="totals__product-total">
|
||||
<span class="totals__subtotal-value">
|
||||
{% comment %} TODO: enable theme-check once `line_items_for` is accepted as valid filter {% endcomment %}
|
||||
{% # theme-check-disable %}
|
||||
{{ cart | line_items_for: product | sum: 'original_line_price' | money }}
|
||||
{% # theme-check-enable %}
|
||||
</span>
|
||||
<p class="totals__subtotal h5">{{ 'sections.quick_order_list.product_total' | t }}</p>
|
||||
</div>
|
||||
<small class="tax-note caption-large rte">
|
||||
{%- if cart.duties_included and cart.taxes_included -%}
|
||||
{%- if shop.shipping_policy.body == blank -%}
|
||||
{{ 'sections.cart.duties_and_taxes_included_shipping_at_checkout_without_policy' | t }}
|
||||
{%- else -%}
|
||||
{{
|
||||
'sections.cart.duties_and_taxes_included_shipping_at_checkout_with_policy_html'
|
||||
| t: link: shop.shipping_policy.url
|
||||
}}
|
||||
{%- endif -%}
|
||||
{%- elsif cart.duties_included == false and cart.taxes_included -%}
|
||||
{%- if shop.shipping_policy.body == blank -%}
|
||||
{{ 'sections.cart.taxes_included_shipping_at_checkout_without_policy' | t }}
|
||||
{%- else -%}
|
||||
{{
|
||||
'sections.cart.taxes_included_shipping_at_checkout_with_policy_html'
|
||||
| t: link: shop.shipping_policy.url
|
||||
}}
|
||||
{%- endif -%}
|
||||
{%- elsif cart.duties_included and cart.taxes_included == false -%}
|
||||
{%- if shop.shipping_policy.body == blank -%}
|
||||
{{ 'sections.cart.duties_included_taxes_at_checkout_shipping_at_checkout_without_policy' | t }}
|
||||
{%- else -%}
|
||||
{{
|
||||
'sections.cart.duties_included_taxes_at_checkout_shipping_at_checkout_with_policy_html'
|
||||
| t: link: shop.shipping_policy.url
|
||||
}}
|
||||
{%- endif -%}
|
||||
{%- elsif cart.duties_included == false and cart.taxes_included == false -%}
|
||||
{%- if shop.shipping_policy.body == blank -%}
|
||||
{{ 'sections.cart.taxes_at_checkout_shipping_at_checkout_without_policy' | t }}
|
||||
{%- else -%}
|
||||
{{
|
||||
'sections.cart.taxes_at_checkout_shipping_at_checkout_with_policy_html'
|
||||
| t: link: shop.shipping_policy.url
|
||||
}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</small>
|
||||
</div>
|
||||
<div class="quick-order-list-total__column large-up-hide">
|
||||
<div class="quick-order-list-buttons">
|
||||
<a
|
||||
href="{{ routes.cart_url }}"
|
||||
class="quick-order-list__button button button--secondary button--full-width"
|
||||
>
|
||||
<span class="quick-order-list__button-text">{{- 'sections.quick_order_list.view_cart' | t -}}</span>
|
||||
</a>
|
||||
<div class="variant-remove-total">
|
||||
{%- render 'loading-spinner' -%}
|
||||
<quick-order-list-remove-all-button
|
||||
class="{% if items_in_cart == 0 %}hidden{% endif %}"
|
||||
data-action="confirm"
|
||||
>
|
||||
<button class="button button--tertiary" type="button">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-remove.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
|
||||
<span class="text-body">{{ 'sections.quick_order_list.remove_all' | t }}</span>
|
||||
</button>
|
||||
</quick-order-list-remove-all-button>
|
||||
</div>
|
||||
</div>
|
||||
<span class="quick-order-list__message caption-large" role="status">
|
||||
<span class="quick-order-list__message-icon hidden">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-checkmark.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
</span>
|
||||
<span class="quick-order-list__message-text"></span>
|
||||
</span>
|
||||
<span class="quick-order-list-error">
|
||||
{% comment %} Populated by JS {% endcomment %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="quick-order-list-total__confirmation hidden">
|
||||
<span class="text-body">
|
||||
{{ 'sections.quick_order_list.remove_all_items_confirmation' | t: quantity: items_in_cart }}
|
||||
</span>
|
||||
<quick-order-list-remove-all-button
|
||||
data-action="remove"
|
||||
>
|
||||
<button
|
||||
class="quick-order-list__button-confirm button button--secondary"
|
||||
type="button"
|
||||
>
|
||||
{{- 'sections.quick_order_list.remove_all' | t -}}
|
||||
</button>
|
||||
</quick-order-list-remove-all-button>
|
||||
<quick-order-list-remove-all-button
|
||||
data-action="cancel"
|
||||
>
|
||||
<button
|
||||
class="quick-order-list__button-cancel button button--tertiary"
|
||||
type="button"
|
||||
>
|
||||
{{- 'sections.quick_order_list.cancel' | t -}}
|
||||
</button>
|
||||
</quick-order-list-remove-all-button>
|
||||
</div>
|
||||
|
||||
<script type="application/json" data-cart-contents>
|
||||
{{ cart | line_items_for: product | map: "variant_id" | json }}
|
||||
</script>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</quick-order-list>
|
||||
<template id="QuickOrderListErrorTemplate-{{ product.id }}">
|
||||
<span class="svg-wrapper">
|
||||
{{ 'icon-error.svg' | inline_asset_content }}
|
||||
</span>
|
||||
<span class="quick-order-list-error-message caption-large" role="alert"></span>
|
||||
</template>
|
||||
</div>
|
||||
@@ -0,0 +1,41 @@
|
||||
{% comment %}
|
||||
Quick Order Product Row
|
||||
Accepts:
|
||||
- item: {Object} Variant or Product object
|
||||
- image: {Object} Product or Variant image (optional)
|
||||
Usage:
|
||||
{% render 'quick-order-product-row' %}
|
||||
{% endcomment %}
|
||||
|
||||
<tr
|
||||
class="product"
|
||||
>
|
||||
<td class="product-item__inner">
|
||||
<div class="product-item__title--wrapper">
|
||||
<div class="variant-item__media">
|
||||
<div class="variant-item__image-container gradient global-media-settings">
|
||||
{%- if image -%}
|
||||
{%- assign img_height = 36 | divided_by: image.aspect_ratio | ceil -%}
|
||||
{{
|
||||
image
|
||||
| image_url: width: 72
|
||||
| image_tag:
|
||||
loading: 'lazy',
|
||||
fetchpriority: 'low',
|
||||
decoding: 'async',
|
||||
class: 'variant-item__image',
|
||||
width: 36,
|
||||
height: img_height,
|
||||
widths: '72',
|
||||
alt: image.alt
|
||||
| escape
|
||||
}}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="small-hide">
|
||||
<a href="{{ item.url }}" class="variant-item__name h4 break">{{ item.title | escape }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -0,0 +1,53 @@
|
||||
{% comment %}
|
||||
Renders share button.
|
||||
Accepts:
|
||||
- block: {Object} passes in the block information.
|
||||
- share_link: {String} url to be added to the input the user will get/copy.
|
||||
|
||||
Usage:
|
||||
{% render 'share-button',
|
||||
block: block,
|
||||
share_link: share_url
|
||||
%}
|
||||
{% endcomment %}
|
||||
<script src="{{ 'share.js' | asset_url }}" defer="defer"></script>
|
||||
|
||||
<share-button id="Share-{{ section.id }}" class="share-button quick-add-hidden" {{ block.shopify_attributes }}>
|
||||
<button class="share-button__button hidden">
|
||||
<span class="svg-wrapper">{{ 'icon-share.svg' | inline_asset_content }}</span>
|
||||
{{ block.settings.share_label | escape }}
|
||||
</button>
|
||||
<details id="Details-{{ block.id }}-{{ section.id }}">
|
||||
<summary class="share-button__button">
|
||||
<span class="svg-wrapper">{{ 'icon-share.svg' | inline_asset_content }}</span>
|
||||
{{ block.settings.share_label | escape }}
|
||||
</summary>
|
||||
<div class="share-button__fallback motion-reduce">
|
||||
<div class="field">
|
||||
<span id="ShareMessage-{{ section.id }}" class="share-button__message hidden" role="status"> </span>
|
||||
<input
|
||||
type="text"
|
||||
class="field__input"
|
||||
id="ShareUrl-{{ section.id }}"
|
||||
value="{{ share_link }}"
|
||||
placeholder="{{ 'general.share.share_url' | t }}"
|
||||
onclick="this.select();"
|
||||
readonly
|
||||
>
|
||||
<label class="field__label" for="ShareUrl-{{ section.id }}">{{ 'general.share.share_url' | t }}</label>
|
||||
</div>
|
||||
<button class="share-button__close hidden">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-close.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.share.close' | t }}</span>
|
||||
</button>
|
||||
<button class="share-button__copy">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-copy.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.share.copy_to_clipboard' | t }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</details>
|
||||
</share-button>
|
||||
@@ -0,0 +1,103 @@
|
||||
{% comment %}
|
||||
Renders social icons.
|
||||
Accepts:
|
||||
- class: {String} a class to be added to the <ul> element (optional).
|
||||
|
||||
Usage:
|
||||
{% render 'social-icons',
|
||||
class: 'my-class'
|
||||
%}
|
||||
{% endcomment %}
|
||||
|
||||
<ul class="list-unstyled list-social{% if class %} {{ class}}{% endif %}" role="list">
|
||||
{%- if settings.social_facebook_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_facebook_link }}" class="link list-social__link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-facebook.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.facebook' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_instagram_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_instagram_link }}" class="link list-social__link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-instagram.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.instagram' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_youtube_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_youtube_link }}" class="link list-social__link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-youtube.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.youtube' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_tiktok_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_tiktok_link }}" class="link list-social__link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-tiktok.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.tiktok' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_twitter_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_twitter_link }}" class="link list-social__link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-twitter.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.twitter' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_pinterest_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_pinterest_link }}" class="link list-social__link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-pinterest.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.pinterest' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_snapchat_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_snapchat_link }}" class="link list-social__link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-snapchat.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.snapchat' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_tumblr_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_tumblr_link }}" class="link list-social__link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-tumblr.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.tumblr' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
{%- if settings.social_vimeo_link != blank -%}
|
||||
<li class="list-social__item">
|
||||
<a href="{{ settings.social_vimeo_link }}" class="link list-social__link">
|
||||
<span class="svg-wrapper">
|
||||
{{- 'icon-vimeo.svg' | inline_asset_content -}}
|
||||
</span>
|
||||
<span class="visually-hidden">{{ 'general.social.links.vimeo' | t }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{%- endif -%}
|
||||
</ul>
|
||||
@@ -0,0 +1,52 @@
|
||||
{% comment %}
|
||||
Renders a swatch input component.
|
||||
Accepts:
|
||||
- id: {String} unique input id
|
||||
- type: {String} input type. Accepts 'radio' or 'checkbox', defaults to 'radio' (optional)
|
||||
- name: {String} input name,
|
||||
- value: {ProductOptionValueDrop} input value
|
||||
- swatch: {SwatchDrop} the swatch drop
|
||||
- product_form_id: {String} id of the form associted with the input
|
||||
- checked: {Boolean} default checked status
|
||||
- disabled: {Boolean} default disabled status (optional)
|
||||
- visually_disabled: {Boolean} style the swatch as disabled, but leave the input enabled (optional)
|
||||
- shape: {String} swatch shape. Accepts 'square', defaults to circle (optional)
|
||||
- help_text: {String} additional content to render inside the label (optional)
|
||||
- additional_props: {String} (optional) additional properties to attach to the input
|
||||
|
||||
Usage:
|
||||
{% render 'swatch-input',
|
||||
id: input_id,
|
||||
name: input_name,
|
||||
value: input_value,
|
||||
swatch: swatch,
|
||||
product_form_id: product_form_id,
|
||||
checked: checked
|
||||
%}
|
||||
{% endcomment %}
|
||||
|
||||
<input
|
||||
type="{{ type | default: 'radio' }}"
|
||||
id="{{ id }}"
|
||||
name="{{ name }}"
|
||||
value="{{ value }}"
|
||||
form="{{ product_form_id }}"
|
||||
class="swatch-input__input{% if visually_disabled %} visually-disabled{% endif %}"
|
||||
{% if checked %}
|
||||
checked
|
||||
{% endif %}
|
||||
{% if disabled %}
|
||||
disabled
|
||||
{% endif %}
|
||||
{% if additional_props %}
|
||||
{{ additional_props }}
|
||||
{% endif %}
|
||||
>
|
||||
<label
|
||||
for="{{ id }}"
|
||||
title="{{ value }}"
|
||||
class="swatch-input__label{% if shape == 'square' %} swatch-input__label--square{% endif %}"
|
||||
>
|
||||
{% render 'swatch', swatch: swatch, shape: shape %}
|
||||
{{ help_text }}
|
||||
</label>
|
||||
@@ -0,0 +1,32 @@
|
||||
{% comment %}
|
||||
Renders a swatch component.
|
||||
Accepts:
|
||||
- swatch: {Object} a swatch object
|
||||
- shape: {String} swatch shape. Accepts 'square', defaults to circle.
|
||||
|
||||
Usage:
|
||||
{% render 'swatch',
|
||||
swatch: value.swatch
|
||||
shape: 'square'
|
||||
%}
|
||||
{% endcomment %}
|
||||
|
||||
{%- liquid
|
||||
assign swatch_value = null
|
||||
if swatch.image
|
||||
assign image_url = swatch.image | image_url: width: 50
|
||||
assign swatch_value = 'url(' | append: image_url | append: ')'
|
||||
assign swatch_focal_point = swatch.image.presentation.focal_point
|
||||
elsif swatch.color
|
||||
assign swatch_value = 'rgb(' | append: swatch.color.rgb | append: ')'
|
||||
endif
|
||||
-%}
|
||||
|
||||
<span
|
||||
{% if swatch_value %}
|
||||
class="swatch{% if shape == 'square' %} swatch--square{% endif %}"
|
||||
style="--swatch--background: {{ swatch_value }};{% if swatch_focal_point %} --swatch-focal-point: {{ swatch_focal_point }};{% endif %}"
|
||||
{% else %}
|
||||
class="swatch swatch--unavailable{% if shape == 'square' %} swatch--square{% endif %}"
|
||||
{% endif %}
|
||||
></span>
|
||||
@@ -0,0 +1,21 @@
|
||||
{%- doc -%}
|
||||
Renders the unit price, including its measurement.
|
||||
|
||||
@param {object} price - The unit price (money or string).
|
||||
@param {object} measurement - The unit_price_measurement object.
|
||||
@param {boolean} [hide_accessibility_label] - Whether to hide the accessibility label (default: false).
|
||||
|
||||
@example
|
||||
{% render 'unit-price', price: variant.unit_price, measurement: variant.unit_price_measurement %}
|
||||
|
||||
@example
|
||||
{% render 'unit-price', price: line_item.unit_price | money_with_currency, measurement: line_item.unit_price_measurement }
|
||||
{%- enddoc -%}
|
||||
<small class="unit-price caption">
|
||||
{%- unless hide_accessibility_label -%}
|
||||
<span class="visually-hidden">{{ 'products.product.price.unit_price' | t }}</span>
|
||||
{%- endunless -%}
|
||||
<span class="price-item price-item--last">
|
||||
{{ price | unit_price_with_measurement: measurement }}
|
||||
</span>
|
||||
</small>
|
||||
Reference in New Issue
Block a user