Retour au catalogue

404 Animated

Page 404 avec chiffres animes en Framer Motion et effets de glitch.

error-pagesmedium Both Responsive a11y
bolddarkuniversalcentered
Theme
"use client";

import { motion } from "framer-motion";
import { ArrowLeft } from "lucide-react";

interface Error404AnimatedProps {
  title?: string;
  description?: string;
  ctaLabel?: string;
  ctaUrl?: string;
}

const ease: [number, number, number, number] = [0.16, 1, 0.3, 1];

const digitVariants = {
  hidden: { opacity: 0, y: 60, rotateX: -90 },
  visible: (i: number) => ({
    opacity: 1, y: 0, rotateX: 0,
    transition: { duration: 0.8, ease, delay: i * 0.15 },
  }),
};

export default function Error404Animated({
  title = "Page introuvable",
  description = "",
  ctaLabel = "Retour",
  ctaUrl = "/",
}: Error404AnimatedProps) {
  return (
    <section className="min-h-screen flex items-center justify-center px-6" style={{ background: "var(--color-background)" }}>
      <div className="text-center">
        <div className="flex items-center justify-center gap-2 mb-8">
          {["4", "0", "4"].map((digit, i) => (
            <motion.span
              key={i}
              custom={i}
              variants={digitVariants}
              initial="hidden"
              animate="visible"
              className="text-7xl md:text-9xl font-black"
              style={{
                color: i === 1 ? "var(--color-accent)" : "var(--color-foreground)",
                textShadow: `0 0 40px var(--color-accent)`,
                opacity: i === 1 ? 0.8 : 1,
              }}
            >
              {digit}
            </motion.span>
          ))}
        </div>

        <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 0.6, delay: 0.5 }}>
          <h1 className="text-xl md:text-2xl font-semibold mb-3" style={{ color: "var(--color-foreground)" }}>{title}</h1>
          {description && <p className="text-sm mb-8 max-w-md mx-auto" style={{ color: "var(--color-foreground-muted)" }}>{description}</p>}
          <a href={ctaUrl} className="inline-flex items-center gap-2 px-6 py-3 rounded-lg text-sm font-semibold transition-opacity hover:opacity-90" style={{ background: "var(--color-accent)", color: "var(--color-background)" }}>
            <ArrowLeft size={15} /> {ctaLabel}
          </a>
        </motion.div>
      </div>
    </section>
  );
}

Avis

404 Animated — React Error-pages Section — Incubator