Sidebar Template
The sidebar template displays filters in a persistent sidebar next to the product grid, ideal for desktop experiences with extensive filtering options.
Implementation¶
Create a new snippet (typically named rebuy-smart-collection-template) and paste the template code. Then render the snippet in your collection template:
Add this at the bottom of collection.liquid or the main file that renders on collection pages.
Template Detection
When Rebuy loads, it searches for a custom template in the theme code. If found, it uses the custom template instead of the standard template.
Template¶
The template wraps content with {% raw %} and {% endraw %} so Vue.js double curly brace syntax doesn't get parsed as Liquid.
{% raw %}
<script id="rebuy-smart-collection-sidebar-template" type="text/template">
<div v-if="shouldShowCollectionsPage()" id="rebuy-smart-collection-sidebar" class="rebuy-smart-collections">
<!-- Smart Collections -->
<div class="rebuy-smart-collections__page">
<!-- Hero Image -->
<div
class="rebuy-smart-collections__hero"
v-bind:class="{ 'rebuy-smart-collections__hero-no-image': !shouldShowHeroImage() }"
>
<div class="rebuy-smart-collections__hero-text">
<h1 class="rebuy-smart-collections__hero-title">{{settings.collectionData?.name || ''}}</h1>
<div v-if="shouldShowHeroDescription()" class="rebuy-smart-collections__hero-description" v-html="settings.collectionData?.description || ''"></div>
</div>
<div v-if="shouldShowHeroImage()" class="rebuy-smart-collections__hero-image">
<img v-bind:src="getCollectionHeroImage()" />
</div>
</div>
<!-- End Hero Image -->
<!-- Skeleton Loader Products -->
<div v-if="!hasLoadedCollectionProducts && smartCollectionsStatus !== 'error'" class="rebuy-smart-collections-skeleton__sidebar rebuy-smart-collections-skeleton">
<div class="rebuy-smart-collections-skeleton__sidebar-filters-container">
<div
v-for="filter in Array(6)"
class="rebuy-smart-collections-skeleton__sidebar-filters-title rebuy-skeleton-background"
></div>
</div>
<div class="rebuy-smart-collections-skeleton__product-container" v-bind:class="resultsGridColumns">
<div v-for="product in Array(12)" class="rebuy-smart-collections-skeleton__product">
<div class="rebuy-smart-collections-skeleton__product-image rebuy-skeleton-background"></div>
<div class="rebuy-smart-collections-skeleton__product-title rebuy-skeleton-background"></div>
<div class="rebuy-smart-collections-skeleton__product-price rebuy-skeleton-background"></div>
</div>
</div>
</div>
<!-- End Skeleton Loader Products -->
<div v-if="smartCollectionsStatus === 'error'">
<p>There was an issue getting Products</p>
</div>
<!-- Collection MainContainer -->
<div v-if="hasLoadedCollectionProducts" class="rebuy-smart-collections-sidebar__main-section">
<!-- Sidebar Filters -->
<div
v-if="shouldShowAggregatedFilters() || hasSelectedFilters()"
class="rebuy-smart-collections__filter-section rebuy-smart-collections-sidebar__filter-section"
>
<h3 class="rebuy-smart-collections-sidebar__filter-section-title rebuy-title">Filters</h3>
<!--- Selected Filters -->
<div
v-if="hasSelectedFilters() && shouldShowSelectedFilters()"
class="rebuy-smart-collections__selected-filters rebuy-smart-collections-sidebar__selected-filters"
>
<div
class="rebuy-smart-collections__selected-filters-header rebuy-smart-collections-sidebar__selected-filters-header"
>
<h4 class="rebuy-smart-collections-sidebar__filter-list-title">Selected Filter</h4>
<button
v-on:click="resetFilters()"
class="rebuy-smart-collections__selected-filters-reset rebuy-smart-collections-sidebar__selected-filters-reset"
>
Reset
</button>
</div>
<div
class="rebuy-smart-collections__selected-filters-body rebuy-smart-collections-sidebar__selected-filters-body"
>
<div
v-if="hasAdjustedPriceFilter"
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span class="rebuy-smart-collections__selected-tag-label">
<span>
<span v-html="shopCurrencySymbol()"> </span>
<span v-html="filterPrice.min"> </span>
</span>
<span>-</span>
<span>
<span v-html="shopCurrencySymbol()"> </span>
<span v-html="handleMaximumPriceFilterLabel()"> </span>
</span>
</span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:alt="handleRemovingFilterLabel('price')"
v-bind:aria-label="handleRemovingFilterLabel('price')"
v-on:click="handleRemovingFilter('price')"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
<div v-if="hasSelectedFilter('availability')">
<div
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span
v-html="handleAvailabilityFilterLabel()"
class="rebuy-smart-collections__selected-tag-label"
></span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:alt="handleRemovingFilterLabel('availability')"
v-bind:aria-label="handleRemovingFilterLabel('availability')"
v-on:click="handleRemovingFilter('availability')"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
</div>
<div
v-for="(tag, index) in collectionSearchData.filters.tags"
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span
v-html="formatTagValue(tag)"
class="rebuy-smart-collections__selected-tag-label"
></span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:alt="handleRemovingFilterLabel('product-tags', tag)"
v-bind:aria-label="handleRemovingFilterLabel('product-tags', tag)"
v-on:click="handleRemovingFilter('product-tags', tag)"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
<div
v-for="(category, index) in collectionSearchData.filters.categories"
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span v-html="category" class="rebuy-smart-collections__selected-tag-label"></span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:alt="handleRemovingFilterLabel('product-type', category)"
v-bind:aria-label="handleRemovingFilterLabel('product-type', category)"
v-on:click="handleRemovingFilter('product-type', category)"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
<div
v-for="(vendor, index) in collectionSearchData.filters.vendors"
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span v-html="vendor" class="rebuy-smart-collections__selected-tag-label"></span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:alt="handleRemovingFilterLabel('vendor', vendor)"
v-bind:aria-label="handleRemovingFilterLabel('vendor', vendor)"
v-on:click="handleRemovingFilter('vendor', vendor)"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
<div
v-for="(option, index) in collectionSearchData.filters.options"
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span
v-html="getReadableFilterValue(option)"
class="rebuy-smart-collections__selected-tag-label"
></span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:alt="handleRemovingFilterLabel('option', option)"
v-bind:aria-label="handleRemovingFilterLabel('option', option)"
v-on:click="handleRemovingFilter('option', option)"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
<div
v-for="(metafieldValue, index) in collectionSearchData.filters.metafields"
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span
v-html="getReadableFilterValue(metafieldValue)"
class="rebuy-smart-collections__selected-tag-label"
></span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:alt="handleRemovingFilterLabel('metafields', metafieldValue)"
v-bind:aria-label="handleRemovingFilterLabel('metafields', metafieldValue)"
v-on:click="handleRemovingFilter('metafields', metafieldValue)"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
</div>
</div>
<!-- Filters Options Desktop -->
<div>
<ul
v-if="hasLoadedInitialCollection"
class="rebuy-smart-collections__filter-list-container rebuy-smart-collections-sidebar__filter-container"
>
<li
v-for="(filter, index) in mappedAggregateFilters"
class="rebuy-smart-collections-sidebar__filter-list"
>
<div
v-if="hasFilterEnabled(filter)"
class="rebuy-smart-collections-sidebar__filter-list-container"
>
<div class="rebuy-smart-collections-sidebar__filter-list-header">
<button
class="rebuy-smart-collections-sidebar__filter-list-toggle"
type="button"
v-bind:alt="filter.isExpanded ? 'Close ' + filter.name : 'Open ' + filter.name"
v-bind:aria-label="filter.isExpanded ? 'Close ' + filter.name : 'Open ' + filter.name"
v-on:click="handleToggleFilterExpansion(filter, index)"
>
<h4
class="rebuy-smart-collections-sidebar__filter-list-title"
v-html="getFilterName(filter)"
></h4>
<div v-if="filterDropDownStyle('plusMinus')">
<rebuy-icon v-if="filter.isExpanded" name="minus"></rebuy-icon>
<rebuy-icon v-if="!filter.isExpanded" name="plus"></rebuy-icon>
</div>
<div v-if="filterDropDownStyle('chevron')">
<rebuy-icon name="chevron-down" v-bind:class="[filter.isExpanded ? 'filter-open' : 'filter-close']"></rebuy-icon>
</div>
</button>
</div>
<div
v-bind:class="[filter.isExpanded ? 'active' : '']"
class="rebuy-smart-collections-sidebar__filter-list-body"
>
<!-- Product tags filter-->
<ul
v-if="filter.type === 'product-tags'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-product-tags"
>
<li
v-for="value in filter.values"
class="rebuy-smart-collections__filter-option-list rebuy-smart-collections-sidebar__filter-list"
>
<input
:id="'rebuy-option-tag-'+ value.tags"
type="checkbox"
class="rebuy-checkbox"
:checked="hasSelectedFilter('product-tags', value.tags)"
v-on:change="handleUpdateSearchQuery(filter.type, value.tags)"
/>
<label
:for="'rebuy-option-tag-'+ value.tags"
class="rebuy-smart-collections__filter-option-checkbox-label"
>
{{ formatTagValue(value.tags) }}
<span
v-if="shouldShowProductFilterCount()"
class="rebuy-smart-collections__filter-label"
>
({{value.numProducts}})
</span>
</label>
</li>
</ul>
<!-- Product vendor filter-->
<ul
v-if="filter.type === 'vendor'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-vendor"
>
<li
v-for="(value, index) in filter.values"
:key="index"
class="rebuy-smart-collections__filter-option-list rebuy-smart-collections-sidebar__filter-list"
>
<input
:id="'rebuy-option-vendor-' + value.vendorAsTag"
type="checkbox"
class="rebuy-checkbox"
:checked="hasSelectedFilter('vendor', value.vendorAsTag)"
v-on:change="handleUpdateSearchQuery(filter.type, value.vendorAsTag)"
/>
<label
:for="'rebuy-option-vendor-' + value.vendorAsTag"
class="rebuy-smart-collections__filter-option-checkbox-label"
>
{{value.vendorAsTag}}
<span
v-if="shouldShowProductFilterCount()"
class="rebuy-smart-collections__filter-label"
>
({{value.numProducts}})
</span>
</label>
</li>
</ul>
<!-- Product availability filter-->
<ul
v-if="filter.type === 'availability'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-availability"
>
<li
class="rebuy-smart-collections__filter-option-list rebuy-smart-collections-sidebar__filter-list"
>
<label class="rebuy-radio-label">
<input
class="radio-input rebuy-radio"
v-on:click="handleUpdateSearchQuery('availability', 'available')"
:checked="hasSelectedFilter('availability', 'available')"
v-bind:value="true"
type="radio"
v-bind:disabled="!hasInStockAvailabilityFilter(filter.values)"
/>
<span
class="radio-label"
v-bind:class="[!hasInStockAvailabilityFilter(filter.values) ? 'disabled' : '']"
>
Available
<span
v-if="hasInStockAvailabilityFilter(filter.values)"
v-html="numsOfAvailabilityFilter(filter.values, 'available')"
class="rebuy-smart-collections__filter-label"
>
</span>
</span>
</label>
</li>
<li
class="rebuy-smart-collections__filter-option-list rebuy-smart-collections-sidebar__filter-list"
>
<label class="rebuy-radio-label">
<input
class="radio-input rebuy-radio"
v-on:click="handleUpdateSearchQuery('availability', 'soldOut')"
:checked="hasSelectedFilter('availability', 'soldOut')"
v-bind:value="false"
type="radio"
v-bind:disabled="!hasSoldOutAvailabilityFilter(filter.values)"
/>
<span
class="radio-label"
v-bind:class="[!hasSoldOutAvailabilityFilter(filter.values) ? 'disabled' : '']"
>
Sold Out
<span
v-if="hasSoldOutAvailabilityFilter(filter.values)"
class="rebuy-smart-collections__filter-label"
v-html="numsOfAvailabilityFilter(filter.values, 'soldOut')"
>
</span>
</span>
</label>
</li>
</ul>
<!-- Product type filter-->
<ul
v-if="filter.type === 'product-type'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-product-type"
>
<li
v-for="value in filter.values"
class="rebuy-smart-collections__filter-option-list rebuy-smart-collections-sidebar__filter-list"
>
<input
:id="'rebuy-option-product-type-' + value.categories"
type="checkbox"
class="rebuy-checkbox"
:checked="hasSelectedFilter('product-type', value.categories)"
v-on:change="handleUpdateSearchQuery(filter.type, value.categories)"
/>
<label
:for="'rebuy-option-product-type-' + value.categories"
class="rebuy-smart-collections__filter-option-checkbox-label"
>
{{value.categories}}
<span
v-if="shouldShowProductFilterCount()"
class="rebuy-smart-collections__filter-label"
>
({{value.numProducts}})
</span>
</label>
</li>
</ul>
<!-- Product price filter-->
<div
v-if="filter.type === 'price'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-price"
>
<div class="rebuy-smart-collections__filter-price-block">
<label
for="rebuy-option-price-from"
v-html="shopCurrencySymbol()"
class="rebuy-smart-collections__filter-price-label"
>
</label>
<input
id="rebuy-option-price-from"
type="number"
class="rebuy-input rebuy-smart-collections__filter-price-input"
placeholder="From"
v-bind:value="filterPrice.min"
min="0"
:max="filterPrice.max"
v-on:change="handleUpdateSearchQuery('price', 'min', {
min: filterPrice.min,
max: filterPrice.max,
price: $event.target.valueAsNumber,
})"
/>
</div>
<div class="rebuy-smart-collections__filter-price-dash">-</div>
<div class="rebuy-smart-collections__filter-price-block">
<label
for="rebuy-option-price-to"
v-html="shopCurrencySymbol()"
class="rebuy-smart-collections__filter-price-label"
>
</label>
<input
id="rebuy-option-price-to"
type="number"
class="rebuy-input rebuy-smart-collections__filter-price-input"
placeholder="To"
v-bind:value="filterPrice.max"
:min="filterPrice.min"
v-on:change="handleUpdateSearchQuery('price', 'max', {
min: filterPrice.min,
max: filterPrice.max,
price: $event.target.valueAsNumber,
})"
/>
</div>
</div>
<!-- Product Option filter-->
<ul
v-if="filter.type === 'product-options'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-product-option"
>
<li
v-for="(optionGroupValue, key) in filter.values"
class="rebuy-smart-collections__filter-option-list"
>
<input
:id="'rebuy-option-product-type-' + key"
type="checkbox"
class="rebuy-checkbox"
:checked="hasSelectedFilter('product-options', getProductOptionFilterString(filter, key))"
v-on:change="handleUpdateSearchQuery('product-options', getProductOptionFilterString(filter, key), key)"
/>
<label
:for="'rebuy-option-product-type-' + key"
class="rebuy-smart-collections__filter-option-checkbox-label"
>
{{key}}
<span
v-if="shouldShowProductFilterCount()"
class="rebuy-smart-collections__filter-label"
>
({{optionGroupValue.numProducts}})
</span>
</label>
</li>
</ul>
<!-- Product metafield filter-->
<ul
v-if="filter.type === 'product-metafield' || filter.type === 'variant-metafield'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-product-type"
>
<li
v-for="metafieldValue in filter.values"
class="rebuy-smart-collections__filter-option-list rebuy-smart-collections-sidebar__filter-list"
>
<input
:id="'rebuy-metafield-' + filter.type + '-' + filter.key + '-' + metafieldValue.value"
type="checkbox"
class="rebuy-checkbox"
:checked="hasSelectedFilter(filter.type, getMetafieldFilterString(filter, metafieldValue))"
v-on:change="handleUpdateSearchQuery(filter.type, getMetafieldFilterString(filter, metafieldValue), metafieldValue.readableValue ?? metafieldValue.value)"
/>
<label
:for="'rebuy-metafield-' + filter.type + '-' + filter.key + '-' + metafieldValue.value"
class="rebuy-smart-collections__filter-option-checkbox-label"
>
<span
v-html="metafieldValue.readableValue ? metafieldValue.readableValue : metafieldValue.value"
></span>
<span
v-if="shouldShowProductFilterCount()"
class="rebuy-smart-collections__filter-label"
>
({{metafieldValue.numProducts}})
</span>
</label>
</li>
</ul>
</div>
</div>
</li>
</ul>
<!--- Filter Skeleton -->
<div></div>
<!--- End Filter Skeleton -->
</div>
</div>
<!-- End Sidebar Filters -->
<div class="rebuy-smart-collections__container">
<!-- Sort By -->
<div
class="rebuy-smart-collections__sort-by rebuy-smart-collections-sidebar__sort-by rebuy-smart-collections-sidebar__sort-by--desktop"
v-if="getSortFilters().length && sortByStyle() === 'sortBySelect'"
>
<label
for="rebuy-smart-collections-sort-options"
class="rebuy-smart-collections-sidebar__sort-by-label"
>
Sort By
</label>
<div>
<select
id="rebuy-smart-collections-sort-options"
class="rebuy-select"
v-model="collectionSearchData.sortBy.field"
v-on:change="($event) => handleUpdateSearchQuery('sort_by', $event.target.value)"
>
<option
v-for="option in settings.sortOptions"
value="sort_by"
v-if="option.enabled"
v-bind:value="option.key"
>
{{ option.label || option.name }}
</option>
</select>
</div>
</div>
<div
v-if="getSortFilters().length && sortByStyle() === 'sortByDropdown'"
class="rebuy-smart-collections__dropdown-menu-container rebuy-smart-collections-sidebar__sort-by rebuy-smart-collections-sidebar__sort-by--desktop"
>
<button
aria-label="Open product filters dropdown"
@click.stop="handleToggleFilterModal('sort')"
@keydown="(e) => handleKeyboardSubmitPrevent(e)"
@keyup="(e) => handleKeyboardSubmit(e, () => { handleToggleFilterModal('product'); })"
class="rebuy-smart-collections__dropdown-menu-trigger"
>
Sort By:
<span class="rebuy-smart-collections__dropdown-menu-title">
{{getSortByLabel(collectionSearchData.sortBy.field)}}
</span>
<rebuy-icon name="chevron-down" v-bind:class="[sortFiltersVisible ? 'filter-open' : 'filter-close']"></rebuy-icon>
</button>
<ul
id="sortSelectMenu"
v-if="sortFiltersVisible"
class="rebuy-smart-collections__dropdown-menu"
>
<li
v-for="option in settings.sortOptions"
v-if="option.enabled"
class="rebuy-smart-collections__dropdown-menu-list-item"
:class="{'rebuy-smart-collections__dropdown-menu-list-item--active': collectionSearchData.sortBy.field === option.key}"
@click="handleUpdateSearchQuery('sort_by', option.key)"
@keydown="(e) => handleKeyboardSubmitPrevent(e)"
@keyup="(e) => handleKeyboardSubmit(e, () => { handleUpdateSearchQuery('sort_by', filter.key); })"
tabindex="0"
>
{{option.label || option.name}}
</li>
</ul>
</div>
<!-- End Sort By -->
<!-- Sort By Trigger (for Mobile) -->
<div
class="rebuy-smart-collections-sidebar__filter-trigger rebuy-smart-collections-sidebar__filter-trigger--mobile"
>
<button
class="rebuy-smart-collections-sidebar__filter-mobile-facets"
@click="showFilterFlyout()"
>
<svg
class="rebuy-smart-collections-sidebar__filter-mobile-facets-icon"
aria-hidden="true"
focusable="false"
role="presentation"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="none"
>
<path
fill-rule="evenodd"
d="M4.833 6.5a1.667 1.667 0 1 1 3.334 0 1.667 1.667 0 0 1-3.334 0ZM4.05 7H2.5a.5.5 0 0 1 0-1h1.55a2.5 2.5 0 0 1 4.9 0h8.55a.5.5 0 0 1 0 1H8.95a2.5 2.5 0 0 1-4.9 0Zm11.117 6.5a1.667 1.667 0 1 0-3.334 0 1.667 1.667 0 0 0 3.334 0ZM13.5 11a2.5 2.5 0 0 1 2.45 2h1.55a.5.5 0 0 1 0 1h-1.55a2.5 2.5 0 0 1-4.9 0H2.5a.5.5 0 0 1 0-1h8.55a2.5 2.5 0 0 1 2.45-2Z"
fill="currentColor"
></path>
</svg>
<span class="rebuy-smart-collections-sidebar__filter-mobile-facets-label"
>Filter and sort</span
>
</button>
</div>
<!-- Main Collection Grid Container -->
<div class="rebuy-smart-collections__container-products" v-bind:class="[resultsGridColumns, productListColumnClass()]">
<div v-if="collectionProducts?.length === 0">
<p>No products found</p>
</div>
<!-- Collection Products -->
<div
v-if="hasLoadedInitialCollection && collectionProducts?.length > 0"
v-for="(product, index) of collectionProducts"
:id="'rebuy-product-id-'+ product.id"
:key="product.id + '-product-' + index"
class="rebuy-smart-collections__product rebuy-smart-collections-sidebar__product"
:class="productImageRatio()"
>
<div v-if="shouldRenderPromoTile(product)" class="rebuy-smart-collections__promo-tile">
<a
v-if="shouldRenderPromoTileAnchor(product)"
v-bind:href="product.content.imageRedirectUrl"
class="rebuy-smart-collections__promo-tile rebuy-product-media rebuy-smart-collections__product-media rebuy-smart-collections__absolute-image-container"
>
<img
v-bind:src="product.content.imageUrl"
alt="promo tile"
class="rebuy-smart-collections__promo-tile-image rebuy-smart-collections__product-image rebuy-smart-collections__absolute-image"
:class="hasImageLoaded(product)"
/>
</a>
<div
v-else
class="rebuy-smart-collections__promo-tile rebuy-product-media rebuy-smart-collections__product-media rebuy-smart-collections__absolute-image-container"
>
<img
v-bind:src="product.content.imageUrl"
alt="promo tile"
class="rebuy-smart-collections__promo-tile-image rebuy-smart-collections__product-image rebuy-smart-collections__absolute-image"
:class="hasImageLoaded(product)"
/>
</div>
</div>
<!-- Image container -->
<a
v-if="shouldRenderProduct(product)"
class="rebuy-product-media rebuy-smart-collections__product-media rebuy-smart-collections__absolute-image-container"
v-bind:href="learnMoreURL(product)"
v-on:click="learnMore(product, index)"
v-bind:alt="'View ' + product.name"
>
<div
v-if="shouldShowFeaturedBadge(product)"
class="rebuy-smart-collections__promoted-tag"
v-html="getFeaturedBadgeHtml()"
></div>
<img
v-bind:src="getProductImage(product, product.selected_variant)"
v-bind:srcset="generateImgSrcset(product)"
class="rebuy-smart-collections__product-image rebuy-smart-collections__absolute-image rebuy-smart-collections__absolute-image--zoomed"
:class="hasImageLoaded(product)"
v-bind:alt="'Image of ' + product.name"
/>
</a>
<!-- Product Info -->
<div v-if="shouldRenderProduct(product)" class="rebuy-smart-collections__product-detail">
<div class="rebuy-product-info">
<!-- Product Title -->
<a
class="rebuy-product-title"
v-bind:href="learnMoreURL(product)"
v-on:click="learnMore(product, index)"
v-html="product.name"
v-bind:alt="'View ' + product.name"
>
</a>
<!-- Product Review -->
<div
class="rebuy-product-review"
v-if="shouldDisplayResultsPageProductRating(product)"
aria-label="product star rating"
>
<span class="rebuy-star-rating">
<span
v-if="product.reviews.star_rating"
class="rebuy-star-rating-value sr-only"
v-html="product.ratings.average + ' stars out of 5 stars'"
>
</span>
<span class="rebuy-star-rating-background"></span>
<span
class="rebuy-star-rating-foreground"
v-bind:style="{ width: getProductReviewRatingPercentage(product) }"
></span>
</span>
<span
class="rebuy-review-count"
v-html="getProductReviewCountHtml(product)"
></span>
</div>
<!-- Product Price -->
<div class="rebuy-product-price">
<div v-if="productOnSale(product)">
<span class="rebuy-money sale">
<span class="sr-only">Sale price</span>
<span v-html="formatMoney(product.selected_variant.price)"></span>
</span>
<span class="rebuy-money compare-at">
<span class="sr-only">Original price</span>
<span
v-html="formatMoney(product.selected_variant.compareAtPrice)"
></span>
</span>
</div>
<div v-if="!productOnSale(product)">
<span class="rebuy-money">
<span class="sr-only">Price</span>
<span v-html="formatMoney(product.selected_variant.price)"></span>
</span>
</div>
</div>
</div>
<!-- Product Options -->
<div class="rebuy-product-options" v-if="shouldShowVariantSelector(product)">
<select
title="Select product variant"
id="rebuy-smart-search-results-variant-select"
class="rebuy-select"
v-bind:aria-label="'variant of ' + product.name"
v-model="product.selected_variant_id"
v-on:change="selectVariant(product)"
>
<option
v-for="variant in product.variants"
v-bind:value="variant.id"
v-html="variant.name"
></option>
</select>
</div>
<!-- Add-to-cart -->
<div class="rebuy-product-actions" v-if="shouldShowAddToCart(product)">
<button
class="rebuy-button rebuy-smart-collections__cta"
v-bind:class="{ working: (product.status != 'ready' && product.status != 'selecting') }"
v-bind:disabled="!(variantAvailable(product.selected_variant)) || (product.status != 'ready' && product.status != 'selecting')"
v-bind:aria-label="buttonAriaLabel(product)"
v-on:click="addToCart(product)"
type="button"
>
<span v-html="buttonLabel(product)"></span>
</button>
</div>
</div>
</div>
</div>
<!-- End Collection Products -->
<!--- Pagination -->
<div
v-if="shouldRenderDefaultPagination()"
class="rebuy-smart-collections__pagination rebuy-smart-collections-sidebar__pagination-section"
v-bind:class="shouldDisplayAmountPerPage() ? 'rebuy-smart-collections__range' : ''"
>
<!--- Range Selection -->
<div v-if="shouldDisplayAmountPerPage()" class="rebuy-range-selection">
<label
class="rebuy-range-selection-label"
v-bind:class="isAmountPerPageSelectionDisabled() && 'rebuy-range-selection-disabled'"
>
Per page
</label>
<select
title="Select products per page"
id="rebuy-smart-search-results-per-page-select"
class="rebuy-select"
v-bind:class="isAmountPerPageSelectionDisabled() && 'rebuy-range-selection-disabled'"
aria-label="products per page"
v-model="productPageSizeCount"
v-on:change="handleUpdatePaginationRange($event.target.value)"
v-bind:disabled="isAmountPerPageSelectionDisabled()"
>
<option
v-for="productsPerPage in pageRangeSelection()"
v-bind:value="productsPerPage.value"
>
{{productsPerPage.value}}
</option>
</select>
</div>
<!--- Page Selection -->
<ul
class="rebuy-smart-collections__pagination rebuy-smart-collections-sidebar__pagination"
>
<li class="rebuy-smart-collections__pagination-label">
<button
v-bind:disabled="smartCollectionsStatus === 'loading'"
v-on:click="handleUpdatingPageCount('decrement')"
class="rebuy-smart-collections__pagination-page rebuy-smart-collections__pagination-arrow"
v-bind:class="{
'rebuy-smart-collections__pagination-arrow--disabled': parseInt(collectionSearchData.currentPage) === 1
}"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
>
<path
d="M15.7049 7.41L14.2949 6L8.29492 12L14.2949 18L15.7049 16.59L11.1249 12L15.7049 7.41Z"
fill="currentColor"
/>
</svg>
</button>
</li>
<li
v-for="(pageNumber, index) in handleGeneratingPageList()"
:key="pageNumber + '-pagination-' + index"
class="rebuy-smart-collections__pagination-label"
v-bind:class="[parseInt(pageNumber) === parseInt(collectionSearchData.currentPage) ? 'active' : '']"
>
<button
v-on:click="handleUpdatingPageCount('manual', pageNumber)"
@keydown="(e) => handleKeyboardSubmitPrevent(e)"
@keyup="(e) => handleKeyboardSubmit(e, () => { handleUpdatingPageCount('manual', pageNumber); })"
class="rebuy-smart-collections__pagination-page"
v-bind:disabled="smartCollectionsStatus === 'loading'"
>
<span v-if="pageNumber"> {{ pageNumber }} </span>
<span
v-if="!pageNumber"
class="rebuy-smart-collections__pagination-icon--disabled"
>
<rebuy-icon name="more-horizontal" class="rebuy-button-icon"></rebuy-icon>
</span>
</button>
</li>
<li class="rebuy-smart-collections__pagination-label">
<button
v-bind:disabled="smartCollectionsStatus === 'loading'"
v-on:click="handleUpdatingPageCount('increment')"
class="rebuy-smart-collections__pagination-page rebuy-smart-collections__pagination-arrow"
v-bind:class="{
'rebuy-smart-collections__pagination-arrow--disabled': parseInt(collectionSearchData.currentPage) === parseInt(totalPages)
}"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
>
<path
d="M9.70492 6L8.29492 7.41L12.8749 12L8.29492 16.59L9.70492 18L15.7049 12L9.70492 6Z"
fill="currentColor"
/>
</svg>
</button>
</li>
</ul>
</div>
<!--- Load More button -->
<div v-if="shouldRenderLoadMore()" class="rebuy-smart-collections__continuous-scroll">
<button
v-if="!hasReachedLastPage()"
v-on:click="handleUpdatingPageCount('continuous')"
class="rebuy-button rebuy-smart-collections__continuous-scroll-button"
v-bind:disabled="smartCollectionsStatus === 'loading'"
>
{{ getLoadMoreText() }}
</button>
</div>
<!--- Continuous Scroll loading spinner -->
<div v-if="shouldRenderContinuousScroll()" class="rebuy-smart-collections__continuous-scroll">
<div
v-if="smartCollectionsStatus === 'loading'"
class="rebuy-smart-collections__continuous-scroll-loader"
>
<span> </span>
</div>
</div>
<!--- End Pagination -->
</div>
</div>
<!--- Filter Flyout Section -->
<div
id="rebuy-smart-search-results-filter-flyout"
role="dialog"
aria-modal="true"
aria-labelledby="filter-flyout-sidebar"
v-bind:aria-hidden="!filterVisible ? 'true' : 'false'"
>
<div
class="rebuy-smart-collections__flyout rebuy-smart-collections__flyout"
v-bind:class="[filterVisible ? 'is-visible' : '']"
>
<div class="rebuy-smart-collections__flyout-inner">
<div class="rebuy-smart-collections__flyout-header rebuy-smart-collections__flyout-header">
<h2 class="rebuy-smart-collections__flyout-header-title">Filter & Sort</h2>
<button
class="rebuy-smart-collections__flyout-close rebuy-smart-collections__flyout-header-close"
type="button"
v-on:click="hideFilterFlyout()"
aria-label="Close Filter Flyout"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
<div class="rebuy-smart-collections__flyout-body rebuy-smart-collections__flyout-body">
<!--- Selected Filters -->
<div
v-if="hasSelectedFilters() && shouldShowSelectedFilters()"
class="rebuy-smart-collections__selected-filters rebuy-smart-collections__flyout-selected-filters rebuy-smart-collections-sidebar__selected-filters"
>
<div
class="rebuy-smart-collections__selected-filters-header rebuy-smart-collections__flyout-selected-filters-header rebuy-smart-collections-sidebar__selected-filters-header"
>
<h4 class="rebuy-smart-collections-sidebar__filter-list-title">Selected Filter</h4>
<button
v-on:click="resetFilters()"
class="rebuy-smart-collections__selected-filters-reset rebuy-smart-collections-sidebar__selected-filters-reset"
>
Reset
</button>
</div>
<div
class="rebuy-smart-collections__selected-filters-body rebuy-smart-collections-sidebar__selected-filters-body"
>
<div
v-if="hasAdjustedPriceFilter"
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span class="rebuy-smart-collections__selected-tag-label">
<span>
<span v-html="shopCurrencySymbol()"> </span>
<span v-html="filterPrice.min"> </span>
</span>
<span>-</span>
<span>
<span v-html="shopCurrencySymbol()"> </span>
<span v-html="handleMaximumPriceFilterLabel()"> </span>
</span>
</span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
alt="Remove price filter"
aria-label="Remove price filter"
v-on:click="handleRemovingFilter('price')"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
<div v-if="hasSelectedFilter('availability')">
<div
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span
v-html="handleAvailabilityFilterLabel()"
class="rebuy-smart-collections__selected-tag-label"
></span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:aria-label="handleRemovingFilterLabel('availability')"
v-bind:aria-label="handleRemovingFilterLabel('availability')"
v-on:click="handleRemovingFilter('availability')"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
</div>
<div
v-for="(tag, index) in collectionSearchData.filters.tags"
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span
v-html="formatTagValue(tag)"
class="rebuy-smart-collections__selected-tag-label"
></span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:alt="'Remove ' + tag + ' tag filter'"
v-bind:aria-label="'Remove ' + tag + ' tag filter'"
v-on:click="handleRemovingFilter('product-tags', tag)"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
<div
v-for="(category, index) in collectionSearchData.filters.categories"
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span
v-html="category"
class="rebuy-smart-collections__selected-tag-label"
></span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:alt="'Remove ' + category + ' product type filter'"
v-bind:aria-label="'Remove ' + category + ' product type filter'"
v-on:click="handleRemovingFilter('product-type', category)"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
<div
v-for="(vendor, index) in collectionSearchData.filters.vendors"
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span
v-html="vendor"
class="rebuy-smart-collections__selected-tag-label"
></span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:alt="'Remove ' + vendor + ' vendor filter'"
v-bind:aria-label="'Remove ' + vendor + ' vendor filter'"
v-on:click="handleRemovingFilter('vendor', vendor)"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
<div
v-for="(option, index) in collectionSearchData.filters.options"
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span
v-html="getReadableFilterValue(option)"
class="rebuy-smart-collections__selected-tag-label"
>
</span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:alt="handleRemovingFilterLabel('option', option)"
v-bind:aria-label="handleRemovingFilterLabel('option', option)"
v-on:click="handleRemovingFilter('option', option)"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
<div
v-for="(metafieldValue, index) in collectionSearchData.filters.metafields"
class="rebuy-smart-collections__selected-filter-tag rebuy-smart-collections-sidebar__selected-filter-tag"
>
<span
v-html="getReadableFilterValue(metafieldValue)"
class="rebuy-smart-collections__selected-tag-label"
></span>
<button
type="button"
class="rebuy-smart-collections__selected-filter-tag-remove rebuy-smart-collections-sidebar__selected-filter-tag-remove"
v-bind:alt="handleRemovingFilterLabel('metafields', metafieldValue)"
v-bind:aria-label="handleRemovingFilterLabel('metafields', metafieldValue)"
v-on:click="handleRemovingFilter('metafields', metafieldValue)"
>
<rebuy-icon name="x"></rebuy-icon>
</button>
</div>
</div>
</div>
<!-- Sort By -->
<div
v-if="getSortFilters().length"
class="rebuy-smart-collections__flyout-sort-by rebuy-smart-collections__sort-by rebuy-smart-collections-sidebar__sort-by rebuy-smart-collections-sidebar__sort-by--mobile"
>
<label
for="rebuy-smart-search-sort-options"
class="rebuy-smart-collections-sidebar__sort-by-label"
>
Sort By
</label>
<div class="rebuy-filter-select-menu">
<select
id="rebuy-smart-search-sort-options"
v-model="collectionSearchData.sortBy.field"
class="rebuy-select"
v-on:change="($event) => handleUpdateSearchQuery('sort_by', $event.target.value)"
>
<option
v-for="filter in getSortFilters()"
v-if="filter.enabled"
v-bind:value="filter.key"
>
{{ filter.label || filter.name }}
</option>
</select>
</div>
</div>
<!-- Filters -->
<ul
v-if="shouldShowAggregatedFilters() || hasSelectedFilters()"
class="rebuy-smart-collections__filter-list-container rebuy-smart-collections-sidebar__filter-container"
>
<li
v-for="(filter, index) in mappedAggregateFilters"
class="rebuy-smart-collections-sidebar__filter-list"
>
<div
v-if="hasFilterEnabled(filter)"
class="rebuy-smart-collections-sidebar__filter-list-container"
>
<div class="rebuy-smart-collections-sidebar__filter-list-header">
<button
class="rebuy-smart-collections-sidebar__filter-list-toggle"
type="button"
v-bind:alt="filter.isExpanded ? 'Close ' + filter.name : 'Open ' + filter.name"
v-bind:aria-label="filter.isExpanded ? 'Close ' + filter.name : 'Open ' + filter.name"
v-on:click="handleToggleFilterExpansion(filter, index)"
>
<h4
class="rebuy-smart-collections-sidebar__filter-list-title"
v-html="getFilterName(filter)"
></h4>
<div v-if="filterDropDownStyle('plusMinus')">
<rebuy-icon v-if="filter.isExpanded" name="minus"></rebuy-icon>
<rebuy-icon v-if="!filter.isExpanded" name="plus"></rebuy-icon>
</div>
<div v-if="filterDropDownStyle('chevron')">
<rebuy-icon name="chevron-down" v-bind:class="[filter.isExpanded ? 'filter-open' : 'filter-close']"></rebuy-icon>
</div>
</button>
</div>
<div
v-bind:class="[filter.isExpanded ? 'active' : '']"
class="rebuy-smart-collections-sidebar__filter-list-body"
>
<ul
v-if="filter.type === 'product-tags'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-product-tags"
>
<li
v-for="value in filter.values"
class="rebuy-smart-collections__filter-option-list rebuy-smart-collections-sidebar__filter-list"
>
<input
:id="'rebuy-option-tag-'+ value.tags"
type="checkbox"
class="rebuy-checkbox"
:checked="hasSelectedFilter('product-tags', value.tags)"
v-on:change="handleUpdateSearchQuery(filter.type, value.tags)"
/>
<label
:for="'rebuy-option-tag-'+ value.tags"
class="rebuy-smart-collections__filter-option-checkbox-label"
>
{{ formatTagValue(value.tags) }}
<span
v-if="shouldShowProductFilterCount()"
class="rebuy-smart-collections__filter-label"
>
({{value.numProducts}})
</span>
</label>
</li>
</ul>
<ul
v-if="filter.type === 'availability'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-availability"
>
<li
class="rebuy-smart-collections__filter-option-list rebuy-smart-collections-sidebar__filter-list"
>
<label class="rebuy-radio-label">
<input
class="radio-input rebuy-radio"
v-on:click="handleUpdateSearchQuery('availability', 'available')"
:checked="hasSelectedFilter('availability', 'available')"
v-bind:value="true"
type="radio"
v-bind:disabled="!hasInStockAvailabilityFilter(filter.values)"
/>
<span
class="radio-label"
v-bind:class="[!hasInStockAvailabilityFilter(filter.values) ? 'disabled' : '']"
>
Available
<span
v-if="hasInStockAvailabilityFilter(filter.values)"
v-html="numsOfAvailabilityFilter(filter.values, 'available')"
class="rebuy-smart-collections__filter-label"
>
</span>
</span>
</label>
</li>
<li
class="rebuy-smart-collections__filter-option-list rebuy-smart-collections-sidebar__filter-list"
>
<label class="rebuy-radio-label">
<input
class="radio-input rebuy-radio"
v-on:click="handleUpdateSearchQuery('availability', 'soldOut')"
:checked="hasSelectedFilter('availability', 'soldOut')"
v-bind:value="false"
type="radio"
v-bind:disabled="!hasSoldOutAvailabilityFilter(filter.values)"
/>
<span
class="radio-label"
v-bind:class="[!hasSoldOutAvailabilityFilter(filter.values) ? 'disabled' : '']"
>
Sold Out
<span
v-if="hasSoldOutAvailabilityFilter(filter.values)"
class="rebuy-smart-collections__filter-label"
v-html="numsOfAvailabilityFilter(filter.values, 'soldOut')"
>
</span>
</span>
</label>
</li>
</ul>
<ul
v-if="filter.type === 'vendor'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-vendor"
>
<li
v-for="(value, index) in filter.values"
:key="index"
class="rebuy-smart-collections__filter-option-list rebuy-smart-collections-sidebar__filter-list"
>
<input
:id="'rebuy-option-vendor-' + value.vendorAsTag"
type="checkbox"
class="rebuy-checkbox"
:checked="hasSelectedFilter('vendor', value.vendorAsTag)"
v-on:change="handleUpdateSearchQuery(filter.type, value.vendorAsTag)"
/>
<label
:for="'rebuy-option-vendor-' + value.vendorAsTag"
class="rebuy-smart-collections__filter-option-checkbox-label"
>
{{value.vendorAsTag}}
<span
v-if="shouldShowProductFilterCount()"
class="rebuy-smart-collections__filter-label"
>
({{value.numProducts}})
</span>
</label>
</li>
</ul>
<ul
v-if="filter.type === 'product-type'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-product-type"
>
<li
v-for="value in filter.values"
class="rebuy-smart-collections__filter-option-list rebuy-smart-collections-sidebar__filter-list"
>
<input
:id="'rebuy-option-product-type-' + value.categories"
type="checkbox"
class="rebuy-checkbox"
:checked="hasSelectedFilter('product-type', value.categories)"
v-on:change="handleUpdateSearchQuery(filter.type, value.categories)"
/>
<label
:for="'rebuy-option-product-type-' + value.categories"
class="rebuy-smart-collections__filter-option-checkbox-label"
>
{{value.categories}}
<span
v-if="shouldShowProductFilterCount()"
class="rebuy-smart-collections__filter-label"
>
({{value.numProducts}})
</span>
</label>
</li>
</ul>
<div
v-if="filter.type === 'price'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-price"
>
<div class="rebuy-smart-collections__filter-price-block">
<label
for="rebuy-option-price-from"
v-html="shopCurrencySymbol()"
class="rebuy-smart-collections__filter-price-label"
>
</label>
<input
id="rebuy-option-price-from"
type="number"
class="rebuy-input rebuy-smart-collections__filter-price-input"
placeholder="From"
v-bind:value="filter.values.min"
v-bind:min="filter.values.min"
v-bind:max="filter.values.max"
v-on:change="handleUpdateSearchQuery('price', 'min', {
min: filter.values.min,
max: filter.values.max,
price: $event.target.value
})"
/>
</div>
<div class="rebuy-smart-collections__filter-price-dash">-</div>
<div class="rebuy-smart-collections__filter-price-block">
<label
for="rebuy-option-price-to"
v-html="shopCurrencySymbol()"
class="rebuy-smart-collections__filter-price-label"
>
</label>
<input
id="rebuy-option-price-to"
type="number"
class="rebuy-input rebuy-smart-collections__filter-price-input"
placeholder="To"
v-bind:value="filter.values.max"
v-bind:min="filter.values.min"
v-bind:max="filter.values.max"
v-on:change="handleUpdateSearchQuery('price', 'max', {
min: filter.values.min,
max: filter.values.max,
price: $event.target.value
})"
/>
</div>
</div>
<ul
v-if="filter.type === 'product-options'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-product-option"
>
<li
v-for="(optionGroupValue, key) in filter.values"
class="rebuy-smart-collections__filter-option-list"
>
<input
:id="'rebuy-option-product-type-' + key"
type="checkbox"
class="rebuy-checkbox"
:checked="hasSelectedFilter('product-options', getProductOptionFilterString(filter, key))"
v-on:change="handleUpdateSearchQuery('product-options', getProductOptionFilterString(filter, key), key)"
/>
<label
:for="'rebuy-option-product-type-' + key"
class="rebuy-smart-collections__filter-option-checkbox-label"
>
{{key}}
<span
v-if="shouldShowProductFilterCount()"
class="rebuy-smart-collections__filter-label"
>
({{optionGroupValue.numProducts}})
</span>
</label>
</li>
</ul>
<ul
v-if="filter.type === 'product-metafield' || filter.type === 'variant-metafield'"
class="rebuy-smart-collections__filter-option rebuy-smart-collections__filter-product-type"
>
<li
v-for="metafieldValue in filter.values"
class="rebuy-smart-collections__filter-option-list rebuy-smart-collections-sidebar__filter-list"
>
<input
:id="'rebuy-metafield-' + filter.type + '-' + filter.key + '-' + metafieldValue.value"
type="checkbox"
class="rebuy-checkbox"
:checked="hasSelectedFilter(filter.type, getMetafieldFilterString(filter, metafieldValue))"
v-on:change="handleUpdateSearchQuery(filter.type, getMetafieldFilterString(filter, metafieldValue), metafieldValue.readableValue ?? metafieldValue.value)"
/>
<label
:for="'rebuy-metafield-' + filter.type + '-' + filter.key + '-' + metafieldValue.value"
class="rebuy-smart-collections__filter-option-checkbox-label"
>
<span
v-html="metafieldValue.readableValue ? metafieldValue.readableValue : metafieldValue.value"
></span>
<span
v-if="shouldShowProductFilterCount()"
class="rebuy-smart-collections__filter-label"
>
({{metafieldValue.numProducts}})
</span>
</label>
</li>
</ul>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
<div
class="rebuy-smart-collections__background"
v-on:click="hideFilterFlyout()"
v-bind:class="[filterVisible ? 'is-visible' : '']"
>
<span></span>
</div>
</div>
<!--- End Filter Flyout Section -->
</div>
</div>
</script>
{% endraw %}
Template Features¶
| Feature | Description |
|---|---|
| Hero section | Collection title, description, and optional hero image |
| Sidebar filters | Persistent filter panel with price, availability, tags, vendors, product types, product options, metafields |
| Mobile flyout | Dedicated filter and sort panel for mobile devices |
| Skeleton loading | Placeholder UI while products load |
| Selected filters | Visual display of active filters with individual remove buttons and reset |
| Sort controls | Desktop select or dropdown-menu style, plus mobile sort in flyout |
| Product grid | Responsive product cards with images, reviews, pricing, and promo tiles |
| Variant selector | Dropdown for multi-variant products |
| Add to cart | Configurable add-to-cart buttons with availability states |
| Pagination | Page numbers, load more button, or continuous scroll |
| Per-page selector | Configurable products-per-page dropdown |
| Accessibility | ARIA labels, screen reader text, keyboard navigation |
Layout Structure¶
+------------------+------------------------+
| Hero Section |
+------------------+------------------------+
| | |
| Sidebar | Products Grid |
| Filters | |
| | - Sort controls |
| - Price | - Product cards |
| - Availability| - Pagination |
| - Tags | |
| - Vendors | |
| - Types | |
| - Options | |
| - Metafields | |
| | |
+------------------+------------------------+
Mobile Considerations¶
On mobile devices: - Sidebar hides and becomes a flyout panel - "Filter and sort" button triggers the flyout - Flyout includes sort controls and all filter options - Flyout has close button and background overlay
Customization¶
Accessing Liquid¶
To access Liquid snippets within the template:
{% raw %}
<!-- Vue.js template code -->
{% endraw %}
{% render 'your-liquid-snippet' %}
{% raw %}
<!-- More Vue.js template code -->
{% endraw %}
CSS Classes¶
All elements use BEM-style class names prefixed with rebuy-smart-collections-sidebar__ and rebuy-smart-collections__. Override these in your theme CSS to customize appearance.