Uma trilha de categorias para sua loja, em React

Trilhas de categorias — a fileira tocável de departamentos acima da grade de uma loja — são os contêineres de rolagem de maior tráfego no e-commerce, e são menus, não carrosséis: cada bloco é um link, nada se encaixa, e meio bloco espiando na borda é o que convida à rolagem.

Arraste a trilha ou use as setas — elas se desativam nas extremidades reais da fileira.

Por que a rolagem nativa vence em uma vitrine

Trilhas de vitrine ficam acima da dobra em páginas nas quais você briga por cada ponto do Lighthouse. Um motor de carrossel entrega dezenas de kilobytes de emulação de gestos para fazer o que o navegador já faz nativamente; esta biblioteca tem ≈5,7 kB min+gzip e deixa a rolagem por conta da plataforma, então não há travamento (jank) de hidratação — a trilha rola antes mesmo do seu JavaScript carregar, o que também significa que ela funciona no HTML renderizado no servidor que seus crawlers veem. Esta própria página é a prova renderizada no servidor: a demo acima rola com o JavaScript desativado.

A página de comparação tem a tabela completa contra Swiper, Embla, keen-slider e react-slick.

Rastreamento de visibilidade é uma funcionalidade de vitrine

Visibilidade por item soa como um detalhe de implementação até você mapeá-la para o merchandising:

Encaixe no seu design system

Os blocos são seus componentes — cards de imagem, círculos, pílulas de texto — cada um carregando um itemId. Altura e largura vêm do seu CSS; o menu não impõe nenhuma dimensão. Avance um item por vez, como um slider de produto, com one-item-scroll, mostre um indicador de progresso de rolagem, ou entregue em RTL para lojas em árabe e hebraico com o exemplo RTL — a trilha é composição, não configuração.

O padrão, no mínimo

Blocos com um itemId, setas vindas dos hooks de visibilidade — a trilha inteira tem menos de quarenta linhas.

CategoryRail.tsx
function CategoryRail({ categories }: { categories: Category[] }) {
  return (
    <ScrollMenu LeftArrow={LeftArrow} RightArrow={RightArrow}>
      {categories.map((category) => (
        <CategoryTile itemId={category.id} key={category.id} {...category} />
      ))}
    </ScrollMenu>
  );
}

function CategoryTile({ itemId, name, image }: CategoryTileProps) {
  // Lazy images for free: placeholders until the tile is on screen.
  const visibility = React.useContext<publicApiType>(VisibilityContext);
  const isVisible = visibility.useIsVisible(itemId, false);
  return (
    <a href={`/category/${itemId}`} className="rail-tile">
      {isVisible ? <img src={image} alt="" /> : <div className="ph" />}
      <span>{name}</span>
    </a>
  );
}

function LeftArrow() {
  const visibility = React.useContext<publicApiType>(VisibilityContext);
  const atStart = visibility.useLeftArrowVisible();
  return (
    <button disabled={atStart} onClick={() => visibility.scrollPrev()}>

    </button>
  );
}

Ou instale como um componente shadcn

O item de registro base scroll-menu é essa mesma trilha — setas estilizadas pelo shadcn, arraste para rolar, barra de rolagem escondida — instalado no seu components/ui/ e estilizado pelos seus tokens:

shadcn
npx shadcn@latest add https://react-horizontal-scrolling-menu.dev/r/scroll-menu.json

Exemplos relacionados

Todos os exemplos (21)