Enhance 404 page with modern design and animations

- Redesigned the 404 error page with a clean background and floating elements for improved visual appeal.
- Introduced glassmorphism effects for the main error container, enhancing the overall aesthetic.
- Added animated elements, including a bouncing 404 number and fun emoji animations, to create a more engaging user experience.
- Implemented responsive design adjustments for better usability on mobile devices.
- Included action buttons for navigation back to the homepage and an about section, improving user interaction.
This commit is contained in:
2025-06-16 21:53:47 +02:00
parent b936c7acb0
commit 7b9da717ec
3 changed files with 474 additions and 13 deletions

View File

View File

@@ -0,0 +1,59 @@
export interface DevelopmentTranslation {
development: {
menu: string;
pageTitle: string;
pageDescription: string;
title: string;
latestCommits: string;
intro: string;
};
}
export const supportedLanguages = ['en', 'nl', 'de', 'fr'] as const;
export function getDevelopmentTranslation(lang: string): DevelopmentTranslation {
return developmentTranslations[lang] || developmentTranslations['en'];
}
export const developmentTranslations: Record<string, DevelopmentTranslation> = {
en: {
development: {
menu: 'Development',
pageTitle: '365DevNet Ecosystem: Development Overview',
pageDescription: 'See the latest development activity, code contributions, and commit history across all repositories in the 365DevNet ecosystem.',
title: 'Dashboard',
latestCommits: 'Last 10 Commits',
intro: 'This page provides a transparent overview of ongoing development activity across all repositories in the 365DevNet ecosystem. The contribution calendar below visually represents code contributions (commits) made over the past year, with more intense squares indicating more active days. Below the calendar, you\'ll find a list of the most recent commits from all repositories, including details about each change. This helps users, contributors, and stakeholders track progress and stay up to date with the latest updates across the entire codebase.'
},
},
nl: {
development: {
menu: 'Ontwikkeling',
pageTitle: '365DevNet Ecosysteem: Ontwikkelingsoverzicht',
pageDescription: 'Bekijk de laatste ontwikkelactiviteit, codebijdragen en commitgeschiedenis van alle repositories in het 365DevNet-ecosysteem.',
title: 'Dashboard',
latestCommits: 'Laatste 10 commits',
intro: 'Deze pagina biedt een transparant overzicht van de lopende ontwikkelactiviteiten in alle repositories van het 365DevNet-ecosysteem. De bijdragekalender hieronder geeft visueel de codebijdragen (commits) van het afgelopen jaar weer, waarbij intensere vakjes meer actieve dagen aangeven. Onder de kalender vindt u een lijst met de meest recente commits uit alle repositories, inclusief details over elke wijziging. Dit helpt gebruikers, bijdragers en belanghebbenden om de voortgang te volgen en op de hoogte te blijven van de laatste updates binnen de gehele codebase.'
},
},
de: {
development: {
menu: 'Entwicklung',
pageTitle: '365DevNet-Ökosystem: Entwicklungsübersicht',
pageDescription: 'Sehen Sie die neuesten Entwicklungsaktivitäten, Codebeiträge und die Commit-Historie aller Repositories im 365DevNet-Ökosystem.',
title: 'Übersicht',
latestCommits: 'Letzte 10 Commits',
intro: 'Diese Seite bietet einen transparenten Überblick über die laufenden Entwicklungsaktivitäten in allen Repositories des 365DevNet-Ökosystems. Der untenstehende Beitragskalender zeigt die Codebeiträge (Commits) des vergangenen Jahres visuell an, wobei intensivere Felder auf aktivere Tage hinweisen. Unter dem Kalender finden Sie eine Liste der neuesten Commits aus allen Repositories mit Details zu jeder Änderung. Dies hilft Nutzern, Mitwirkenden und Stakeholdern, den Fortschritt zu verfolgen und über die neuesten Updates im gesamten Codebestand informiert zu bleiben.'
},
},
fr: {
development: {
menu: 'Développement',
pageTitle: 'Écosystème 365DevNet : Aperçu du développement',
pageDescription: 'Consultez les dernières activités de développement, contributions de code et historique des commits de tous les dépôts de l\'écosystème 365DevNet.',
title: 'Tableau de bord',
latestCommits: '10 derniers commits',
intro: 'Cette page offre un aperçu transparent de l\'activité de développement en cours dans tous les dépôts de l\'écosystème 365DevNet. Le calendrier des contributions ci-dessous représente visuellement les contributions de code (commits) réalisées au cours de l\'année écoulée, les cases les plus intenses indiquant les jours les plus actifs. Sous le calendrier, vous trouverez une liste des commits les plus récents de tous les dépôts, avec des détails sur chaque modification. Cela aide les utilisateurs, contributeurs et parties prenantes à suivre la progression et à rester informés des dernières mises à jour dans l\'ensemble du code.'
},
},
};

View File

@@ -5,19 +5,421 @@ import { getHomePermalink } from '~/utils/permalinks';
const title = `Error 404`;
---
<style>
/* Clean background without animated gradients */
.clean-404-bg {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
}
/* Enhanced floating elements for 404 */
.floating-elements-404 {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
overflow: hidden;
}
.floating-shape-404 {
position: absolute;
opacity: 0.2;
animation: float404 25s infinite linear;
}
.shape-404-1 {
top: 10%;
left: 5%;
width: 100px;
height: 100px;
background: linear-gradient(135deg, rgba(255,255,255,0.25), rgba(255,255,255,0.05));
border-radius: 50%;
backdrop-filter: blur(15px);
border: 2px solid rgba(255,255,255,0.15);
animation-delay: 0s;
}
.shape-404-2 {
top: 20%;
right: 10%;
width: 80px;
height: 80px;
background: linear-gradient(135deg, rgba(255,255,255,0.2), rgba(255,255,255,0.03));
border-radius: 20px;
backdrop-filter: blur(12px);
border: 2px solid rgba(255,255,255,0.1);
animation-delay: -8s;
}
.shape-404-3 {
bottom: 15%;
left: 15%;
width: 60px;
height: 60px;
background: linear-gradient(135deg, rgba(255,255,255,0.3), rgba(255,255,255,0.08));
border-radius: 50%;
backdrop-filter: blur(10px);
border: 2px solid rgba(255,255,255,0.2);
animation-delay: -15s;
}
.shape-404-4 {
top: 60%;
right: 25%;
width: 120px;
height: 40px;
background: linear-gradient(135deg, rgba(255,255,255,0.15), rgba(255,255,255,0.04));
border-radius: 20px;
backdrop-filter: blur(18px);
border: 2px solid rgba(255,255,255,0.12);
animation-delay: -12s;
}
.shape-404-5 {
bottom: 40%;
right: 5%;
width: 70px;
height: 70px;
background: linear-gradient(135deg, rgba(255,255,255,0.22), rgba(255,255,255,0.06));
border-radius: 15px;
backdrop-filter: blur(14px);
border: 2px solid rgba(255,255,255,0.14);
animation-delay: -20s;
}
/* Main 404 container with glassmorphism - wider for better text layout */
.error-container {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(25px);
border: 2px solid rgba(255, 255, 255, 0.3);
border-radius: 32px;
padding: 4rem 4rem;
text-align: center;
box-shadow:
0 32px 80px rgba(0, 0, 0, 0.15),
0 0 0 1px rgba(255, 255, 255, 0.1) inset;
position: relative;
z-index: 10;
max-width: 800px;
width: 90%;
margin: 2rem;
animation: slideUpFade 1s cubic-bezier(0.4, 0, 0.2, 1) forwards;
opacity: 0;
transform: translateY(40px);
}
/* Animated 404 number */
.error-number {
font-size: clamp(6rem, 15vw, 12rem);
font-weight: 900;
background: linear-gradient(135deg,
#667eea 0%,
#764ba2 25%,
#f093fb 50%,
#f5576c 75%,
#4facfe 100%);
background-size: 300% 300%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
animation: gradientShift 8s ease-in-out infinite, bounce404 2s ease-in-out infinite;
letter-spacing: -0.05em;
line-height: 0.9;
margin-bottom: 1.5rem;
text-shadow: 0 0 50px rgba(102, 126, 234, 0.3);
position: relative;
}
/* Glitch effect on hover */
.error-number:hover {
animation: gradientShift 8s ease-in-out infinite, glitch404 0.5s ease-in-out;
}
/* Error messages - ensure single line for title */
.error-title {
font-size: clamp(2rem, 5vw, 3rem);
font-weight: 700;
color: #1a1a1a;
margin-bottom: 1rem;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
white-space: nowrap;
}
.error-subtitle {
font-size: 1.2rem;
color: #4a5568;
margin-bottom: 2rem;
line-height: 1.6;
font-weight: 500;
}
/* Action buttons */
.action-buttons {
display: flex;
gap: 1.5rem;
justify-content: center;
flex-wrap: wrap;
margin-top: 2rem;
}
.btn-primary-404 {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
padding: 1rem 2.5rem;
border-radius: 50px;
text-decoration: none;
font-weight: 600;
font-size: 1.1rem;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 15px 35px rgba(102, 126, 234, 0.4);
border: 2px solid transparent;
position: relative;
overflow: hidden;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary-404::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
transition: left 0.6s;
}
.btn-primary-404:hover::before {
left: 100%;
}
.btn-primary-404:hover {
transform: translateY(-8px) scale(1.05);
box-shadow: 0 30px 60px rgba(102, 126, 234, 0.6);
}
.btn-secondary-404 {
background: rgba(255, 255, 255, 0.3);
backdrop-filter: blur(15px);
color: #1a1a1a;
padding: 1rem 2.5rem;
border-radius: 50px;
text-decoration: none;
font-weight: 600;
font-size: 1.1rem;
border: 2px solid rgba(255, 255, 255, 0.4);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-secondary-404:hover {
background: rgba(255, 255, 255, 0.5);
transform: translateY(-5px);
border-color: rgba(255, 255, 255, 0.6);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
}
/* Fun emoji animations */
.fun-emoji {
font-size: 2rem;
animation: spin404 3s linear infinite;
display: inline-block;
margin: 0 0.5rem;
}
.fun-emoji:nth-child(2) {
animation-delay: -1s;
}
.fun-emoji:nth-child(3) {
animation-delay: -2s;
}
/* Dark mode styles */
:global(.dark) .error-container {
background: rgba(30, 30, 50, 0.95);
border-color: rgba(255, 255, 255, 0.2);
box-shadow:
0 32px 80px rgba(0, 0, 0, 0.4),
0 0 0 1px rgba(255, 255, 255, 0.05) inset;
}
:global(.dark) .error-title {
color: #e2e8f0;
}
:global(.dark) .error-subtitle {
color: #a0aec0;
}
:global(.dark) .btn-secondary-404 {
color: #e2e8f0;
}
/* Animations */
@keyframes gradientShift {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
@keyframes backgroundMove {
0% { transform: translateX(0) translateY(0); }
100% { transform: translateX(-50px) translateY(-50px); }
}
@keyframes float404 {
0%, 100% {
transform: translateY(0px) rotate(0deg) scale(1);
opacity: 0.2;
}
25% {
transform: translateY(-40px) rotate(90deg) scale(1.2);
opacity: 0.35;
}
50% {
transform: translateY(-20px) rotate(180deg) scale(1.1);
opacity: 0.25;
}
75% {
transform: translateY(-35px) rotate(270deg) scale(1.25);
opacity: 0.4;
}
}
@keyframes bounce404 {
0%, 100% {
transform: translateY(0px);
}
50% {
transform: translateY(-20px);
}
}
@keyframes glitch404 {
0%, 100% { transform: translateX(0); }
20% { transform: translateX(-5px); }
40% { transform: translateX(5px); }
60% { transform: translateX(-3px); }
80% { transform: translateX(3px); }
}
@keyframes slideUpFade {
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes spin404 {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Responsive design */
@media (max-width: 768px) {
.error-container {
padding: 3rem 2rem;
margin: 1rem;
border-radius: 24px;
width: 95%;
}
.error-title {
white-space: normal;
font-size: clamp(1.5rem, 6vw, 2rem);
}
.action-buttons {
flex-direction: column;
align-items: center;
gap: 1rem;
}
.btn-primary-404,
.btn-secondary-404 {
width: 100%;
max-width: 280px;
justify-content: center;
padding: 1rem 2rem;
}
.error-subtitle {
font-size: 1.1rem;
}
}
/* Additional playful elements */
.sparkle {
position: absolute;
width: 4px;
height: 4px;
background: white;
border-radius: 50%;
animation: sparkle404 2s linear infinite;
}
.sparkle:nth-child(1) { top: 20%; left: 20%; animation-delay: 0s; }
.sparkle:nth-child(2) { top: 30%; right: 25%; animation-delay: 0.5s; }
.sparkle:nth-child(3) { bottom: 25%; left: 30%; animation-delay: 1s; }
.sparkle:nth-child(4) { bottom: 35%; right: 20%; animation-delay: 1.5s; }
@keyframes sparkle404 {
0%, 100% { opacity: 0; transform: scale(0); }
50% { opacity: 1; transform: scale(1); }
}
</style>
<Layout metadata={{ title }}>
<section class="flex items-center h-full p-16">
<div class="container flex flex-col items-center justify-center px-5 mx-auto my-8">
<div class="max-w-md text-center">
<h2 class="mb-8 font-bold text-9xl">
<span class="sr-only">Error</span>
<span class="text-primary">404</span>
<section class="clean-404-bg">
<div class="floating-elements-404">
<div class="floating-shape-404 shape-404-1"></div>
<div class="floating-shape-404 shape-404-2"></div>
<div class="floating-shape-404 shape-404-3"></div>
<div class="floating-shape-404 shape-404-4"></div>
<div class="floating-shape-404 shape-404-5"></div>
<!-- Sparkle effects -->
<div class="sparkle"></div>
<div class="sparkle"></div>
<div class="sparkle"></div>
<div class="sparkle"></div>
</div>
<div class="error-container">
<h1 class="error-number">404</h1>
<h2 class="error-title">
Oops! Page Not Found
<span class="fun-emoji">🚀</span>
<span class="fun-emoji">⚡</span>
<span class="fun-emoji">💻</span>
</h2>
<p class="text-3xl font-semibold md:text-3xl">Sorry, we couldn't find this page.</p>
<p class="mt-4 mb-8 text-lg text-muted dark:text-slate-400">
But dont worry, you can find plenty of other things on our homepage.
<p class="error-subtitle">
Looks like this page took an unexpected detour through cyberspace!
Don't worry though - I can help you get back on track to discover my automation expertise.
</p>
<a rel="noopener noreferrer" href={getHomePermalink()} class="btn ml-4">Back to homepage</a>
<div class="action-buttons">
<a href={getHomePermalink()} class="btn-primary-404">
<span>🏠</span> Back to Home
</a>
<a href="/aboutme" class="btn-secondary-404">
<span>👨‍💻</span> About Richard
</a>
</div>
</div>
</section>