Listing

<link media="all" rel="stylesheet" href="/assets/themes/default/css/listing.css?cb=">

<div class="category-listing category-listing--4-columns grid-container" data-module="categoryListing" data-page-size="2" data-endpoint="/components/preview/listing-api-results--{0}?category&#x3D;{0}" data-initial-category="">
    <div class="grid-x align-center category-listing__section-header">

        <div class="section-header">
            <p class="section-header__eyebrow">Section Eyebrow text</p>
            <h2 class="section-header__title">Section Header</h2>

        </div>
    </div>
    <div class="grid-x category-listing__filters">
        <div class="cell">
            <div class="grid_container listing-filter listing-filter--4-buttons">
                <div class="listing-filter__button">
                    <button class="listing-filter__cta js-apply-filter-btn selected" data-category=default>Standard</button>
                </div>
                <div class="listing-filter__button">
                    <button class="listing-filter__cta js-apply-filter-btn " data-category=merchants>Merchants</button>
                </div>
                <div class="listing-filter__button">
                    <button class="listing-filter__cta js-apply-filter-btn " data-category=blogs>Blogs</button>
                </div>
                <div class="listing-filter__button">
                    <button class="listing-filter__cta js-apply-filter-btn " data-category=events>Events</button>
                </div>
            </div>
        </div>
    </div>
    <div class="grid-x grid-padding-x category-listing__results">
    </div>

    <div class="grid-x align-center">
        <button class="category-listing__load-more-button">Load more</button>
    </div>
</div>
{{#if firstInstance}}
<link media="all" rel="stylesheet" href="/assets/themes/{{theme}}/css/listing.css?cb={{cacheBuster}}">
{{/if}}

<div class="category-listing category-listing--{{numberOfColumns}}-columns grid-container" data-module="categoryListing" data-page-size="{{pageSize}}" data-endpoint="{{endpoint}}" data-initial-category="{{initialCategory}}" >
    {{#if sectionHeader}}
    <div class="grid-x align-center category-listing__section-header">
        {{> @section-header sectionHeader }}
    </div>
    {{/if}}
    <div class="grid-x category-listing__filters">
        <div class="cell">
            {{> @listing-filter filter}}
        </div>
    </div>
    <div class="grid-x grid-padding-x category-listing__results">
    </div>

    <div class="grid-x align-center">
        <button class="category-listing__load-more-button">{{loadMoreText}}</button>
    </div>
</div>
{
  "theme": "default",
  "firstInstance": true,
  "filter": {
    "listingFilterButtons": [
      {
        "category": "default",
        "text": "Standard"
      },
      {
        "category": "merchants",
        "text": "Merchants"
      },
      {
        "category": "blogs",
        "text": "Blogs"
      },
      {
        "category": "events",
        "text": "Events"
      }
    ]
  },
  "sectionHeader": {
    "title": "Section Header",
    "eyebrow": "Section Eyebrow text"
  },
  "numberOfColumns": 4,
  "endpoint": "/components/preview/listing-api-results--{0}?category={0}",
  "pageSize": "2",
  "loadMoreText": "Load more"
}
  • Content:
    .listing-filter {
        display: flex;
        justify-content: center;
        width: 100%;
    
        &--0-buttons,
        &--1-buttons {
            display: none;
        }
    
        &__button {
            padding: 0 rem(10);
        }
    
        &__cta {
            @extend %primary-cta;
    
            &.selected {
                @extend %secondary-cta;
                pointer-events: none;
            }
        }
    }
    
  • URL: /components/raw/listing/_listing-filter.scss
  • Filesystem Path: source/patterns/03-components/listings/listing/_listing-filter.scss
  • Size: 355 Bytes
  • Content:
    import LazyLoader from '../../../../js/utils/lazy-loader';
    import format from '../../../../js/utils/string';
    import { getQueryStringParameter, setQueryParams } from '../../../../js/utils/routing';
    
    export class CategoryListing {
        constructor(container) {
            this.container = container;
            this.loadMoreButton = this.container.querySelector('.category-listing__load-more-button');
            this.resultsContainer = this.container.querySelector('.category-listing__results');
            this.filterButtons = this.container.querySelectorAll('.js-apply-filter-btn');
            this.categoryQueryStringParameterName = 'category';
            this.init();
        }
    
        init() {
            this.parseQueryParams();
            this.setUpLazyLoader();
            this.addEventListener();
        }
    
        parseQueryParams() {
            const category = getQueryStringParameter(this.categoryQueryStringParameterName);
            if (category) {
                const filterButton = this.container.querySelector(`.js-apply-filter-btn[data-category='${category}']`);
                if (filterButton) {
                    this.resetButtons();
                    filterButton.classList.add('selected');
                }
            }
        }
    
        setUpLazyLoader() {
            this.lazyLoader = new LazyLoader(
                this.container.dataset.endpoint,
                this.container.dataset.pageSize,
                this.loadMoreButton,
                this.resultsContainer,
                null,
                'get',
            );
    
            const { endpoint } = this.container.dataset;
            const { category } = this.container.querySelector('.js-apply-filter-btn.selected').dataset;
            this.endpoint = endpoint;
            this.updatedEndPoint = format(this.endpoint, category);
            this.lazyLoader.setEndPoint(this.updatedEndPoint);
            this.lazyLoader.load();
        }
    
        addEventListener() {
            this.filterButtons.forEach((btn) => {
                btn.addEventListener('click', (event) => {
                    event.preventDefault();
                    const button = event.target;
                    this.resetButtons();
                    button.classList.add('selected');
                    const { category } = button.dataset;
                    this.updatedEndPoint = format(this.endpoint, category);
                    this.lazyLoader.reset();
                    this.lazyLoader.setEndPoint(this.updatedEndPoint);
                    this.lazyLoader.load();
                    setQueryParams(this.categoryQueryStringParameterName, category);
                });
            });
        }
    
        resetButtons() {
            this.filterButtons.forEach((btn) => {
                btn.classList.remove('selected');
            });
        }
    }
    
    export default (module) => new CategoryListing(module);
    
  • URL: /components/raw/listing/listing.js
  • Filesystem Path: source/patterns/03-components/listings/listing/listing.js
  • Size: 2.7 KB
  • Content:
    @import 'source/scss/01-settings/_import';
    @import 'source/scss/02-tools/_import';
    @import './_listing-filter';
    
    .category-listing {
        &__section-header {
            margin: rem(50) 0;
        }
    
        &__filters {
            margin-bottom: rem(20);
        }
    
        &__no-results {
            @extend %p--body;
            margin: rem(20) 0;
            text-align: center;
            width: 100%;
        }
    
        &__card-wrapper {
            @extend %spacer-large;
            width: 100%;
    
            @include breakpoint(medium) {
                width: calc(100% / 3);
    
                .category-listing--4-columns & {
                    width: calc(100% / 4);
                }
            }
        }
    
        &__results {
            &.loading {
                @extend %lazy-loader;
            }
        }
    
        &__load-more-button {
            @extend %primary-cta;
        }
    }
    
  • URL: /components/raw/listing/listing.scss
  • Filesystem Path: source/patterns/03-components/listings/listing/listing.scss
  • Size: 792 Bytes

No notes defined.