Retour au catalogue

404 Illustrated

Page 404 avec illustration SVG decorative et liens de navigation.

error-pagessimple Both Responsive a11y
playfullightuniversalcentered
Theme
"use client";

import { motion } from "framer-motion";
import { Home, ArrowRight } from "lucide-react";

interface NavLink { label: string; href: string; }

interface Error404IllustratedProps {
  title?: string;
  description?: string;
  ctaLabel?: string;
  ctaUrl?: string;
  links?: NavLink[];
}

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

export default function Error404Illustrated({
  title = "Oups ! Page introuvable",
  description = "",
  ctaLabel = "Retour",
  ctaUrl = "/",
  links = [],
}: Error404IllustratedProps) {
  return (
    <section className="min-h-screen flex items-center justify-center px-6" style={{ background: "var(--color-background)" }}>
      <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.6, ease }} className="text-center max-w-lg">
        {/* SVG illustration */}
        <svg className="w-48 h-48 mx-auto mb-8" viewBox="0 0 200 200" fill="none">
          <circle cx="100" cy="100" r="80" stroke="var(--color-border)" strokeWidth="2" strokeDasharray="8 4" />
          <text x="100" y="110" textAnchor="middle" fontSize="48" fontWeight="bold" fill="var(--color-accent)" opacity="0.6">404</text>
          <circle cx="70" cy="80" r="5" fill="var(--color-foreground-light)" />
          <circle cx="130" cy="80" r="5" fill="var(--color-foreground-light)" />
          <path d="M 75 120 Q 100 110 125 120" stroke="var(--color-foreground-light)" strokeWidth="3" fill="none" strokeLinecap="round" />
        </svg>

        <h1 className="text-2xl md:text-3xl font-bold mb-3" style={{ color: "var(--color-foreground)" }}>{title}</h1>
        {description && <p className="text-base mb-8" 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 mb-8" style={{ background: "var(--color-accent)", color: "var(--color-background)" }}>
          <Home size={15} /> {ctaLabel}
        </a>

        {links.length > 0 && (
          <div className="flex items-center justify-center gap-6">
            {links.map((link) => (
              <a key={link.label} href={link.href} className="flex items-center gap-1 text-sm font-medium hover:opacity-70 transition-opacity" style={{ color: "var(--color-foreground-muted)" }}>
                {link.label} <ArrowRight size={12} />
              </a>
            ))}
          </div>
        )}
      </motion.div>
    </section>
  );
}

Avis

404 Illustrated — React Error-pages Section — Incubator