# Before vs After: Skeleton Loader Redesign ## Visual Comparison ### BEFORE: Blocking Full-Page Overlay ❌ ``` ┌────────────────────────────────────────────────┐ │ [EN] [ES] ← Click Spanish │ │ │ │ ╔═════════════════════════════════════════╗ │ │ ║ FULL-PAGE OVERLAY (z-index: 50) ║ │ │ ║ ┌─────────────────────────────────────┐ ║ │ │ ║ │ ▓▓▓▓▓▓▓▓▓▓▓▓ Skeleton Header │ ║ │ │ ║ │ ▓▓▓▓▓▓ Skeleton Badges │ ║ │ │ ║ │ │ ║ │ │ ║ │ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓ │ ║ │ │ ║ │ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓ │ ║ │ │ ║ │ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓ │ ║ │ │ ║ │ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓ │ ║ │ │ ║ │ Sidebar Main Content Sidebar │ ║ │ │ ║ └─────────────────────────────────────┘ ║ │ │ ╚═════════════════════════════════════════╝ │ │ │ │ ⛔ USER CANNOT SCROLL │ │ ⛔ USER CANNOT CLICK ANYTHING │ │ ⛔ EVERYTHING BLOCKED │ └────────────────────────────────────────────────┘ ``` **Problems:** - ⛔ Full page blocked - ⛔ Cannot scroll - ⛔ Cannot interact with any element - ⛔ Renders 150+ skeleton DOM elements - ⛔ Heavy visual distraction - ⛔ Poor UX - feels "broken" --- ### AFTER: Inline Loading States ✅ ``` ┌────────────────────────────────────────────────┐ │ [EN] [ES ⟳] ← Inline spinner in button │ │ │ │ ┌─────────────────────────────────────────┐ │ │ │ CV Content (opacity: 0.5, blur: 1px) │ │ │ │ │ │ │ │ TECHNICAL CONSULTANT | FULL-STACK... │ │ │ │ (slightly faded during transition) │ │ │ │ │ │ │ │ Skills Main Content Skills │ │ │ │ • React Experience • Docker │ │ │ │ • Node Senior Dev... • K8s │ │ │ │ • HTMX 2015-2024 • Go │ │ │ │ │ │ │ │ (Content smoothly fading/transitioning) │ │ │ └─────────────────────────────────────────┘ │ │ │ │ ✅ USER CAN SCROLL │ │ ✅ USER CAN READ CONTENT │ │ ✅ ONLY CV CONTENT TRANSITIONING │ └────────────────────────────────────────────────┘ ``` **Benefits:** - ✅ No blocking overlay - ✅ Can scroll during transition - ✅ Can read content (50% opacity still readable) - ✅ Inline button spinner shows progress - ✅ Subtle, elegant transition - ✅ Great UX - feels smooth and responsive --- ## Technical Comparison | Aspect | Before (Overlay) | After (Inline) | |--------|------------------|----------------| | **Blocking** | Full page blocked | Non-blocking | | **DOM Elements** | 150+ skeleton elements | 0 new elements | | **CSS Lines** | ~150 lines | ~20 lines | | **JavaScript** | Hyperscript show/hide | None (HTMX built-in) | | **Scroll** | ⛔ Disabled | ✅ Enabled | | **Interaction** | ⛔ Blocked | ✅ Allowed | | **Visual** | Heavy skeleton | Subtle fade/blur | | **Accessibility** | Blocks everything | Respects reduced motion | | **Performance** | Higher memory | Lower memory | | **Code** | Complex overlay | Pure CSS transitions | --- ## User Flow Comparison ### BEFORE: Blocking Flow 1. User clicks [ES] button 2. **EVERYTHING STOPS** 🛑 3. Full-page overlay appears (jarring) 4. Skeleton placeholders render 5. User waits... cannot do anything 6. Content loads 7. Overlay fades out 8. User can interact again 9. **Total perceived time: ~1000ms** (feels slow) ### AFTER: Non-Blocking Flow 1. User clicks [ES] button 2. **Inline spinner appears in button** ⟳ 3. **CV content fades slightly** (subtle) 4. User can still scroll/read 5. Content swaps smoothly 6. Content fades back to 100% 7. **Total time: ~500ms** (feels instant) 8. User never lost control --- ## CSS Code Comparison ### BEFORE: Complex Overlay ```css /* Full-page overlay */ #skeleton-loader { position: fixed; top: 50px; left: 0; right: 0; bottom: 0; background: var(--bg-gray); z-index: 50; opacity: 0; pointer-events: none; transition: opacity 250ms ease-in-out; display: flex; justify-content: center; padding: 20px 0; } #skeleton-loader.active { opacity: 1; pointer-events: all; } /* Skeleton shapes */ .skeleton { background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); background-size: 200% 100%; animation: skeleton-pulse 1.5s ease-in-out infinite; border-radius: 4px; } @keyframes skeleton-pulse { 0%, 100% { background-position: 200% 0; } 50% { background-position: 0 0; } } .skeleton-header { height: 120px; margin-bottom: 30px; } .skeleton-badges { height: 40px; width: 60%; } .skeleton-title { height: 24px; width: 40%; } .skeleton-content { height: 16px; } .skeleton-grid { display: grid; grid-template-columns: 250px 1fr 250px; } /* ... 100+ more lines ... */ ``` ### AFTER: Simple Inline States ```css /* Inline loading states - clean and simple */ .cv-page-content-wrapper.htmx-swapping { opacity: 0.5; transform: scale(0.99); pointer-events: none; filter: blur(1px); } .cv-page-content-wrapper.htmx-settling { opacity: 1; transform: scale(1); pointer-events: auto; filter: blur(0); } @media (prefers-reduced-motion: reduce) { .cv-page-content-wrapper.htmx-swapping { transform: none; filter: none; opacity: 0.7; } } ``` **Result:** From 150+ lines to 20 lines (87% reduction) --- ## HTMX Integration ### BEFORE: Manual JavaScript Control ```html