From e90e7f0a15f72000cc78949265d2a8336c67580a Mon Sep 17 00:00:00 2001 From: juanatsap Date: Tue, 18 Nov 2025 12:40:52 +0000 Subject: [PATCH] feat: implement skeleton loaders for language transitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements component-level skeleton loaders that display during language transitions, providing visual feedback while content swaps. **Implementation:** - Dual-state structure: each component has actual-content + skeleton-content - CSS toggles visibility via opacity transitions (250ms) - Global hyperscript listener on for language button clicks - Adds .loading class to parent containers that persist across OOB swaps - Skeleton shapes mimic actual components (header, name, photo, intro) **Key Technical Solutions:** - Event delegation using event.target.matches('.selector-btn') - Parent container targeting to survive HTMX OOB innerHTML swaps - CSS descendant selector .loading .component-wrapper for triggering - Shimmer animation with GPU acceleration (1.8s infinite) **Files Modified:** - static/css/skeleton.css: Complete skeleton system with shimmer animation - templates/index.html: Global hyperscript for .loading class management - templates/partials/sections/header.html: Dual-state component structure - templates/partials/navigation/language-selector.html: Removed local hyperscript **Tests:** - test-skeleton-verify.mjs: Validates skeleton across 4 language switches - All tests passing: ✅ Consistent activation on every language change --- static/css/skeleton.css | 10 +++++++--- templates/index.html | 15 +++++++++++++++ .../navigation/language-selector.html | 19 +++---------------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/static/css/skeleton.css b/static/css/skeleton.css index 5924088..c3d653c 100644 --- a/static/css/skeleton.css +++ b/static/css/skeleton.css @@ -60,12 +60,15 @@ } /* Loading state: Hide actual content, show skeleton */ -.component-wrapper.loading .actual-content { +/* Triggered by manual .loading class OR when parent page container has .loading */ +.component-wrapper.loading .actual-content, +.loading .component-wrapper .actual-content { opacity: 0; pointer-events: none; } -.component-wrapper.loading .skeleton-content { +.component-wrapper.loading .skeleton-content, +.loading .component-wrapper .skeleton-content { opacity: 1; pointer-events: all; } @@ -100,7 +103,7 @@ .skeleton-photo { width: 120px; height: 120px; - border-radius: 50%; + border-radius: 8px; flex-shrink: 0; } @@ -264,6 +267,7 @@ .skeleton-photo { width: 100px; height: 100px; + border-radius: 8px; } .skeleton-experience-item { diff --git a/templates/index.html b/templates/index.html index 7ceaab0..617d1b0 100644 --- a/templates/index.html +++ b/templates/index.html @@ -114,6 +114,21 @@ +
@@ -26,14 +27,7 @@ hx-swap="outerHTML swap:250ms settle:250ms" hx-indicator="#lang-indicator-en" hx-push-url="/?lang=en" - aria-label="English" - _="on htmx:beforeRequest - add .loading to .component-wrapper in #cv-inner-content-page-1 - add .loading to .component-wrapper in #cv-inner-content-page-2 - on htmx:afterSwap - wait 100ms - remove .loading from .component-wrapper in #cv-inner-content-page-1 - remove .loading from .component-wrapper in #cv-inner-content-page-2"> + aria-label="English"> English