Skip to content

Commit 027290b

Browse files
committed
feat: add playful custom 404 Page Not Found component
- Created a new NotFound component in src/pages/NotFound/NotFound.tsx - Used framer-motion to add animated ghost illustration and pulsating shadow - Designed the page using Tailwind CSS for a playful and modern aesthetic - Imported and configured the NotFound component as a wildcard catch-all route (*) in Router.tsx to handle all invalid URLs
1 parent e7b8fc8 commit 027290b

2 files changed

Lines changed: 62 additions & 0 deletions

File tree

src/Routes/Router.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import ContributorProfile from "../pages/ContributorProfile/ContributorProfile.t
99
import Home from "../pages/Home/Home.tsx";
1010
import Activity from "../pages/Activity.tsx";
1111
import PrivacyPolicy from "../pages/Privacy/PrivacyPolicy.tsx"; // ✅ Updated import path to match your new folder structure
12+
import NotFound from "../pages/NotFound/NotFound.tsx";
1213

1314
const Router = () => {
1415
return (
@@ -25,6 +26,9 @@ const Router = () => {
2526

2627
{/* Privacy Policy page route */}
2728
<Route path="/privacy" element={<PrivacyPolicy />} />
29+
30+
{/* 404 Not Found Catch-All Route */}
31+
<Route path="*" element={<NotFound />} />
2832
</Routes>
2933
);
3034
};

src/pages/NotFound/NotFound.tsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { Link } from "react-router-dom";
2+
import { Home, Ghost } from "lucide-react";
3+
import { motion } from "framer-motion";
4+
5+
const NotFound = () => {
6+
return (
7+
<div className="flex flex-col items-center justify-center min-h-[75vh] px-4 text-center overflow-hidden">
8+
<motion.div
9+
initial={{ opacity: 0, y: 30 }}
10+
animate={{ opacity: 1, y: 0 }}
11+
transition={{ duration: 0.6, ease: "easeOut" }}
12+
className="relative z-10"
13+
>
14+
{/* Animated Ghost Illustration */}
15+
<div className="relative flex flex-col items-center justify-center mb-8">
16+
<motion.div
17+
animate={{ y: [0, -20, 0] }}
18+
transition={{ repeat: Infinity, duration: 3.5, ease: "easeInOut" }}
19+
className="relative z-10"
20+
>
21+
<Ghost className="h-32 w-32 text-indigo-500 dark:text-indigo-400 drop-shadow-2xl" strokeWidth={1.5} />
22+
</motion.div>
23+
24+
{/* Floating Shadow */}
25+
<motion.div
26+
animate={{ scale: [1, 0.7, 1], opacity: [0.3, 0.1, 0.3] }}
27+
transition={{ repeat: Infinity, duration: 3.5, ease: "easeInOut" }}
28+
className="absolute -bottom-6 w-20 h-5 bg-gray-400 dark:bg-black rounded-[100%] blur-md"
29+
/>
30+
</div>
31+
32+
<h1 className="text-7xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-indigo-600 dark:from-blue-400 dark:to-indigo-400 mb-3 drop-shadow-sm">
33+
404
34+
</h1>
35+
<h2 className="text-2xl md:text-3xl font-bold text-gray-800 dark:text-gray-100 mb-4">
36+
Spooky... This page is a ghost town.
37+
</h2>
38+
39+
<p className="text-gray-600 dark:text-gray-400 mb-10 max-w-md mx-auto leading-relaxed">
40+
The link you followed has vanished into the digital void, or maybe it never existed at all!
41+
</p>
42+
43+
<Link
44+
to="/"
45+
className="inline-flex items-center justify-center gap-2 px-8 py-3.5 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 text-white font-semibold rounded-2xl shadow-lg transition-all duration-300 hover:shadow-indigo-500/30 hover:-translate-y-1 active:translate-y-0"
46+
>
47+
<Home className="h-5 w-5" />
48+
<span>Teleport Back Home</span>
49+
</Link>
50+
</motion.div>
51+
52+
{/* Background decorative blobs */}
53+
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[600px] bg-blue-100/30 dark:bg-blue-900/10 rounded-full blur-[100px] -z-10 pointer-events-none" />
54+
</div>
55+
);
56+
};
57+
58+
export default NotFound;

0 commit comments

Comments
 (0)