Scroll Híbrido

Neste artigo veremos como criar a funcionalidade de scroll híbrido nas páginas da categoria e nos resultados da pesquisa.

Mas o que é um scroll híbrido? Basicamente, misture as experiências de:

  • Um scroll infinito no qual os produtos são carregados na lista à medida que o usuário rola na página, sem ver o rodapé até que todos os produtos tenham terminado de carregar (assim como um aplicativo nativo em um telefone celular).
  • Uma experiência de paginação clássica em que o usuário tem controle sobre quantos produtos ver por página, deixando o rodapé mais visível do que no caso de scroll infinito.

O scroll híbrido funciona da seguinte maneira:

  • Ao carregar a página exibimos 12, 16 ou 20 itens (dependendo do que está definido no tpls que veremos neste tutorial)
  • Quando o usuário inicia a rolagem, mais produtos são carregados automaticamente (ocultando o rodapé) até atingirem 50.
  • Em seguida, um botão "ver mais produtos" e o rodapé do site são exibidos.
  • Clicar neste botão carrega mais produtos e retorna ao modo "scroll infinito"
  • Quando o usuário rola, mais produtos são recarregados automaticamente até chegarem a mais 60.
  • Os passos são repetidos

Desta forma, garantimos que o usuário verá o conteúdo que está abaixo da lista de produtos, por exemplo, o rodapé, onde pode haver informações relevantes, como métodos de pagamento, métodos de envio, detalhes de contato, etc.

Além disso, se o usuário acessar os detalhes de um produto e voltar, ele não perderá a quantidade de produtos carregados anteriormente.

HTML

1. A primeira coisa que vamos fazer é no arquivo templates/category.tpl excluir o grid que você tem até agora e substituí-lo com o seguinte:

{% if products %}
    <div class="js-product-table row">
        {% include 'snipplets/product_grid.tpl' %}
    </div>
    {% if pages.current == 1 and not pages.is_last %}
         <div class="text-center mt-5 mb-5">
            <a class="js-load-more btn btn-primary">
                <span class="js-load-more-spinner" style="display:none;">{% include "snipplets/svg/sync-alt.tpl" with {svg_custom_class: "icon-inline icon-spin"} %}</span>
                {{ 'Mostrar más productos' | t }}
            </a>
        </div>
         <div id="js-infinite-scroll-spinner" class="mt-5 mb-5 text-center w-100" style="display:none">
            {% include "snipplets/svg/sync-alt.tpl" with {svg_custom_class: "icon-inline icon-3x svg-icon-text icon-spin"} %} 
        </div>
    {% endif %}
{% else %}
    <p class="text-center">
        {{(has_filters ? "No tenemos productos en esas variantes. Por favor, intentá con otros filtros." : "Próximamente") | translate}}
    </p>
{% endif %}

É importante manter os IDs e as classes "js -...", pois iremos conectá-los ao JavaScript.

Também precisamos adicionar a seguinte linha no começo do tpl (se você já tem, não é necessário fazer este passo)

{% paginate by 12 %}

Isso define a paginação inicial (o número de produtos que são carregados antes de você começar a fazer scroll) ao carregar a página.

2. No template search.tpl na pasta de templates, aplique uma alteração muito semelhante à etapa anterior:

{% if products %}
    <div class="js-product-table row">
        {% include 'snipplets/product_grid.tpl' %}
    </div>
    {% if pages.current == 1 and not pages.is_last %}
        <div class="text-center mt-5 mb-5">
            <a class="js-load-more btn btn-primary">
                <span class="js-load-more-spinner" style="display:none;">{% include "snipplets/svg/sync-alt.tpl" with {svg_custom_class: "icon-inline icon-spin"} %}</span>
                {{ 'Mostrar más productos' | t }}
            </a>
        </div>
         <div id="js-infinite-scroll-spinner" class="mt-5 mb-5 text-center w-100" style="display:none">
             {% include "snipplets/svg/sync-alt.tpl" with {svg_custom_class: "icon-inline icon-3x svg-icon-text icon-spin"} %} 
        </div>
    {% endif %}
{% else %}
    <p class="text-center">
        {{ "No hubo resultados para tu búsqueda" | translate }}
    </p>
{% endif %}

E também adicionar (ou substituir) o valor de paginação no início do tpl

{% paginate by 12 %}

2. Adicionamos a classe js-hide-footer-while-scrolling ao container geral do rodapé.

3. Finalmente, para a parte HTML, precisamos adicionar uma pasta SVG dentro da pasta snipplets, onde vamos criar o snipplet para o ícone que gira indicando que mais produtos estão sendo carregados, com o nome sync-alt.tpl

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M483.515 28.485L431.35 80.65C386.475 35.767 324.485 8 256 8 123.228 8 14.824 112.338 8.31 243.493 7.971 250.311 13.475 256 20.301 256h28.045c6.353 0 11.613-4.952 11.973-11.294C66.161 141.649 151.453 60 256 60c54.163 0 103.157 21.923 138.614 57.386l-54.128 54.129c-7.56 7.56-2.206 20.485 8.485 20.485H492c6.627 0 12-5.373 12-12V36.971c0-10.691-12.926-16.045-20.485-8.486zM491.699 256h-28.045c-6.353 0-11.613 4.952-11.973 11.294C445.839 370.351 360.547 452 256 452c-54.163 0-103.157-21.923-138.614-57.386l54.128-54.129c7.56-7.56 2.206-20.485-8.485-20.485H20c-6.627 0-12 5.373-12 12v143.029c0 10.691 12.926 16.045 20.485 8.485L80.65 431.35C125.525 476.233 187.516 504 256 504c132.773 0 241.176-104.338 247.69-235.493.339-6.818-5.165-12.507-11.991-12.507z"/></svg>

CSS

Requisito:

Ter adicionado helper classes em seu layout. Você pode seguir este pequeno tutorial para fazer isso (é só copiar e colar algumas classes, não leva mais que 1 minuto).

Adicionamos o seguinte SASS de cores em style-colors.scss.tpl (ou na stylesheet do seu layout que possui as cores e fontes da loja). Lembre-se de que as variáveis de cores e fontes podem variar em relação ao seu layout:

@mixin prefix($property, $value, $prefixes: ()) {
  @each $prefix in $prefixes {
      #{'-' + $prefix + '-' + $property}: $value;
  }
    #{$property}: $value;
}


{# /* // Buttons */ #}


.btn{
  text-decoration: none;
  text-align: center;
  border: 0;
  cursor: pointer;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  text-transform: uppercase;
  background: none;
  @include prefix(transition, all 0.4s ease, webkit ms moz o);
  &:hover,
  &:focus{
    outline: 0;
    opacity: 0.8;
  }
  &[disabled],
  &[disabled]:hover{
    opacity: 0.5;
    cursor: not-allowed;
    outline: 0;
  }
  &-default{
    padding: 10px 15px; 
    background-color: rgba($main-foreground, .2);
    color: $main-foreground;
    fill: $main-foreground;
    font-weight: bold;
  }
  &-primary{
    padding: 15px;
    background-color: $primary-color;
    color: $main-background;
    fill: $main-background;
    letter-spacing: 4px;
    &:hover{
      color: $main-background;
      fill: $main-background;
    }
  }


  &-block{
    float: left;
    width: 100%;
  }
}


button{
  @extend %body-font;
  cursor: pointer;
  &:focus{
    outline: 0;
    opacity: 0.8;
  }
}

JS

⚠️ A partir do dia 30 de janeiro de 2023, a biblioteca jQuery será removida do código de nossas lojas, portanto, a função "$" não poderá ser utilizada.

1. JavaScript precisam ser adicionados no arquivo store.js.tpl (ou onde você tem suas funções JS). O código que precisamos é o seguinte:

{% if template == 'category' or template == 'search' %}

        !function() {

            {# /* // Infinite scroll */ #}

            {% if pages.current == 1 and not pages.is_last %}
                LS.hybridScroll({
                    productGridSelector: '.js-product-table',
                    spinnerSelector: '#js-infinite-scroll-spinner',
                    loadMoreButtonSelector: '.js-load-more',
                    hideWhileScrollingSelector: ".js-hide-footer-while-scrolling",
                    productsBeforeLoadMoreButton: 50,
                    productsPerPage: 12
                });
            {% endif %}
        }();

{% endif %}

En este JS podemos encontrar algunas propiedades que podés cambiar:

PropiedadeDescrição
productGridSelectorÉ o seletor para o div que contém a lista de produtos
spinnerSelectorO seletor do ícone giratório que é exibido quando o usuário alcança a parte inferior de tudo na tela e nenhum produto foi carregado ainda.
loadMoreButtonSelectorUsado para ocultar ou mostrar o botão "Ver mais produtos
hideWhileScrollingSelectorComo o nome indica, ele serve para ocultar elementos enquanto o modo “scroll infinito” é ativado
productsBeforeLoadMoreButtonÉ a quantidade de produtos que serão carregados até que o botão "Ver mais" seja exibido
productsPerPage
Número de produtos exibidos quando a página é carregada. Deve corresponder ao {% paginate by 12 %} no category.tpl e search.tpl

Caso você precise aplicar o JS logo após o carregamento dos produtos, você pode usar a seguinte função:

afterLoaded: function() {


},

Dentro do contexto, seria aplicado da seguinte forma:

spinnerSelector: '#js-infinite-scroll-spinner',
loadMoreButtonSelector: '.js-load-more',
hideWhileScrollingSelector: ".js-hide-footer-while-scrolling",
productsBeforeLoadMoreButton: 50,
productsPerPage: 12,
afterLoaded: function() {
    console.log("test");
},

Isso pode ser útil caso você use um plug-in como o Masonry, em que você precisa acomodar os elementos sempre que forem carregados.

Pronto, você já tem o scroll híbrido em execução.