feat(web): add smooth page transitions and WASM loading states

- Implement navigation state tracking with optimistic UI updates
- Add loading spinner and error handling for WASM initialization
- Insert browser yield points during game initialization to prevent freezing
- Redesign leaderboard with tabbed navigation and mock data structure
- Add utility CSS classes for consistent page layouts
This commit is contained in:
2025-12-29 03:33:43 -06:00
parent d3514b84e9
commit 3bb3908853
22 changed files with 602 additions and 328 deletions
+77 -2
View File
@@ -66,19 +66,88 @@
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Loading spinner - CSS animation runs on compositor thread,
continues even during main thread blocking */
.loading-spinner {
width: 48px;
height: 48px;
border: 4px solid rgb(250 204 21 / 0.3);
border-top-color: rgb(250 204 21);
border-radius: 50%;
animation: spin 1s linear infinite;
}
/* Error indicator - X mark with shake animation */
@keyframes shake {
0%, 100% { transform: translateX(0); }
20%, 60% { transform: translateX(-4px); }
40%, 80% { transform: translateX(4px); }
}
.error-indicator {
width: 48px;
height: 48px;
position: relative;
animation: shake 0.5s ease-out;
}
.error-indicator::before,
.error-indicator::after {
content: '';
position: absolute;
width: 4px;
height: 32px;
background: rgb(239 68 68);
border-radius: 2px;
top: 50%;
left: 50%;
}
.error-indicator::before {
transform: translate(-50%, -50%) rotate(45deg);
}
.error-indicator::after {
transform: translate(-50%, -50%) rotate(-45deg);
}
@layer utilities {
.page-container {
@apply mx-auto max-w-3xl py-8 px-4;
}
.card {
@apply border border-yellow-400/20 rounded-md bg-transparent p-6 shadow-[0_4px_20px_rgba(250,204,21,0.08)];
}
.title-hover {
transition: transform 0.2s ease-out, filter 0.2s ease-out;
}
.title-hover:hover {
transform: scale(1.03);
filter: brightness(1.15);
}
.glimmer-text {
.title-base {
position: relative;
}
.title-base::before {
content: attr(data-text);
position: absolute;
inset: 0;
background: linear-gradient(
90deg,
rgb(156 163 175) 0%,
@@ -93,5 +162,11 @@
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: glimmer 3s ease-in-out infinite;
opacity: 0;
transition: opacity 0.2s ease-out;
}
.title-base.title-glimmer::before {
opacity: 1;
}
}