Un rail de catégories pour votre boutique, en React

Les rails de catégories — la rangée cliquable de rayons au-dessus d'une grille de vitrine — sont les conteneurs de défilement les plus fréquentés en e-commerce, et ce sont des menus, pas des carrousels : chaque vignette est un lien, rien ne s'aligne, et une demi-vignette qui dépasse au bord est ce qui invite au défilement.

Faites glisser le rail ou utilisez les flèches — elles se désactivent aux véritables extrémités de la rangée.

Pourquoi le défilement natif gagne sur une vitrine

Les rails de vitrine vivent au-dessus de la ligne de flottaison, sur des pages où vous vous battez pour chaque point Lighthouse. Un moteur de carrousel embarque des dizaines de kilo-octets d'émulation de gestes pour faire ce que le navigateur fait nativement ; cette bibliothèque pèse ≈5,7 kB min+gzip et laisse le défilement à la plateforme, donc il n'y a pas de saccade d'hydratation — le rail défile avant même le chargement de votre JavaScript, ce qui signifie aussi qu'il fonctionne dans le HTML rendu côté serveur que voient vos robots d'indexation. Cette page elle-même en est la preuve rendue côté serveur : la démo ci-dessus défile avec JavaScript désactivé.

La page de comparaison contient le tableau complet face à Swiper, Embla, keen-slider et react-slick.

Le suivi de visibilité est une fonctionnalité de vitrine

La visibilité par élément ressemble à un détail d'implémentation jusqu'à ce que vous la rapprochiez du merchandising :

Adaptez-le à votre système de design

Les vignettes sont vos composants — cartes images, cercles, pastilles de texte — chacune portant un itemId. La hauteur et la largeur viennent de votre CSS ; le menu n'impose aucune dimension. Avancez d'un élément à la fois comme un slider produit avec one-item-scroll, affichez un indicateur de progression de défilement, ou livrez-le en RTL pour les boutiques arabes et hébraïques avec l'exemple RTL — le rail est de la composition, pas de la configuration.

Le motif, minimal

Des vignettes avec un itemId, des flèches issues des hooks de visibilité — le rail complet fait moins de quarante lignes.

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 installez-le comme composant shadcn

L'élément de registre de base scroll-menu est ce rail — flèches stylées shadcn, glisser pour défiler, barre de défilement masquée — installé dans votre components/ui/ et stylé par vos tokens :

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

Exemples associés

Tous les exemples (21)