Retour au catalogue

Breadcrumb Animated

Breadcrumb avec animation slide-in sur chaque element et separateurs chevron.

breadcrumbsimple Both Responsive a11y
minimaluniversalstacked
Theme
"use client";

import { useState, useEffect } from "react";
import { ChevronRight, Home } from "lucide-react";

interface BreadcrumbItem {
  label: string;
  href?: string;
  icon?: "home";
}

interface BreadcrumbAnimatedProps {
  items?: BreadcrumbItem[];
}

const mockItems: BreadcrumbItem[] = [
  { label: "Accueil", href: "#", icon: "home" },
  { label: "Produits", href: "#" },
  { label: "Electronique", href: "#" },
  { label: "Smartphones" },
];

export default function BreadcrumbAnimated({
  items = mockItems,
}: BreadcrumbAnimatedProps) {
  const [visibleCount, setVisibleCount] = useState(0);

  useEffect(() => {
    if (visibleCount < items.length) {
      const timer = setTimeout(() => {
        setVisibleCount((prev) => prev + 1);
      }, 120);
      return () => clearTimeout(timer);
    }
  }, [visibleCount, items.length]);

  return (
    <nav
      className="py-4 px-6"
      style={{ background: "var(--color-background)" }}
      aria-label="Fil d'Ariane"
    >
      <ol className="flex items-center gap-1.5 text-sm">
        {items.map((item, i) => {
          const isVisible = i < visibleCount;
          const isLast = i === items.length - 1;

          return (
            <li
              key={i}
              className="flex items-center gap-1.5 transition-all duration-300 ease-out"
              style={{
                opacity: isVisible ? 1 : 0,
                transform: isVisible ? "translateX(0)" : "translateX(-12px)",
                transitionDelay: `${i * 80}ms`,
              }}
            >
              {i > 0 && (
                <ChevronRight
                  size={14}
                  className="shrink-0"
                  style={{ color: "var(--color-foreground-light)" }}
                />
              )}
              {isLast ? (
                <span
                  className="font-medium"
                  style={{ color: "var(--color-foreground)" }}
                  aria-current="page"
                >
                  {item.label}
                </span>
              ) : (
                <a
                  href={item.href || "#"}
                  className="inline-flex items-center gap-1.5 transition-colors duration-200 hover:underline underline-offset-2"
                  style={{ color: "var(--color-foreground-muted)" }}
                >
                  {item.icon === "home" && <Home size={14} />}
                  {item.label}
                </a>
              )}
            </li>
          );
        })}
      </ol>

      <style>{`
        @keyframes breadcrumb-slide-in {
          from { opacity: 0; transform: translateX(-12px); }
          to   { opacity: 1; transform: translateX(0); }
        }
      `}</style>
    </nav>
  );
}

Avis

Breadcrumb Animated — React Breadcrumb Section — Incubator