docs: refactor skeleton loader architecture from overlay to component-based
Changed skeleton loader implementation strategy from separate overlay to built-in component states: ARCHITECTURE CHANGE: - Before: Separate skeleton-loader.html overlay positioned absolutely over content - After: Each component contains both actual content and skeleton state markup - Skeleton states toggle via CSS classes (.loading) on component wrappers - No separate overlay layer - skeleton lives inside each component IMPLEMENTATION
This commit is contained in:
@@ -32,7 +32,7 @@ This will transform the current instant language switch into a premium, modern w
|
||||
**Desired User Experience (from screenshots):**
|
||||
1. User clicks language button (EN or ES)
|
||||
2. Current content fades out (200-300ms)
|
||||
3. Skeleton loaders appear - gray pulsing boxes matching the layout structure
|
||||
3. Skeleton loaders appear - gray pulsing boxes matching INSIDE of the CV (so, a toggle of the content)
|
||||
4. New language content loads from server
|
||||
5. Skeleton loaders fade out and new content fades in (200-300ms)
|
||||
6. Total smooth, professional transition feel
|
||||
@@ -98,15 +98,22 @@ This will transform the current instant language switch into a premium, modern w
|
||||
<implementation>
|
||||
**Recommended Implementation Strategy:**
|
||||
|
||||
**Step 1: Create Skeleton Loader HTML Structure**
|
||||
**Step 1: Add Skeleton States to Existing Components**
|
||||
|
||||
Create a new template or partial: `templates/partials/skeleton-loader.html`
|
||||
Modify existing CV component templates to include built-in skeleton states:
|
||||
|
||||
This should contain a simplified version of your CV layout with placeholder boxes:
|
||||
- Header skeleton (circular avatar placeholder, horizontal bars for name/title)
|
||||
- Left sidebar skeleton (rectangular blocks for skills)
|
||||
- Main content skeleton (blocks for experience entries)
|
||||
- Right sidebar skeleton (blocks for additional skills)
|
||||
- `templates/partials/cv-header.html` - Add skeleton state markup inside the component
|
||||
- `templates/partials/skills-*.html` - Add skeleton placeholders for skill blocks
|
||||
- `templates/partials/experience-entry.html` - Add skeleton placeholders for experience blocks
|
||||
- Each component should have both actual content and skeleton markup, toggled via CSS classes
|
||||
|
||||
Example structure:
|
||||
```html
|
||||
<div class="component-wrapper">
|
||||
<div class="actual-content"><!-- Real CV content --></div>
|
||||
<div class="skeleton-content hidden"><!-- Skeleton placeholders --></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**Step 2: Create Skeleton CSS Animations**
|
||||
|
||||
@@ -126,21 +133,29 @@ Add to `static/css/main.css` or create `static/css/skeleton.css`:
|
||||
50% { background-position: 0 0; }
|
||||
}
|
||||
|
||||
/* Skeleton container - hidden by default */
|
||||
.skeleton-overlay {
|
||||
/* Component state toggling */
|
||||
.component-wrapper .actual-content {
|
||||
opacity: 1;
|
||||
transition: opacity 250ms ease;
|
||||
}
|
||||
|
||||
.component-wrapper .skeleton-content {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: white;
|
||||
z-index: 10;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 250ms ease;
|
||||
}
|
||||
|
||||
.skeleton-overlay.active {
|
||||
/* Loading state - toggle content visibility */
|
||||
.component-wrapper.loading .actual-content {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.component-wrapper.loading .skeleton-content {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
}
|
||||
@@ -160,36 +175,39 @@ Add to `static/css/main.css` or create `static/css/skeleton.css`:
|
||||
|
||||
Modify `templates/partials/navigation/language-selector.html`:
|
||||
- Add `hx-swap="outerHTML swap:250ms settle:250ms"`
|
||||
- Add `hx-indicator="#skeleton-loader"` to show skeleton during request
|
||||
- Add hyperscript to manage skeleton visibility
|
||||
- Add hyperscript to toggle `.loading` class on component wrappers
|
||||
- Coordinate timing with component fade-in/out transitions
|
||||
|
||||
**Step 4: Add Skeleton Loader to Main Template**
|
||||
**Step 4: Ensure Component Wrappers Have Proper Classes**
|
||||
|
||||
Insert the skeleton loader overlay into your main CV template:
|
||||
- Position it absolutely over the content area
|
||||
- Initially hidden with `opacity: 0`
|
||||
- Activated via HTMX events or hyperscript
|
||||
Verify that CV component wrappers in templates have:
|
||||
- `.component-wrapper` class for CSS targeting
|
||||
- Both `.actual-content` and `.skeleton-content` children
|
||||
- Proper positioning context (relative positioning on wrapper)
|
||||
|
||||
**Step 5: HTMX Event Handling with Hyperscript**
|
||||
|
||||
Add hyperscript behavior to show/hide skeleton:
|
||||
Add hyperscript behavior to toggle loading state on components:
|
||||
|
||||
```hyperscript
|
||||
on htmx:beforeRequest from #language-selector
|
||||
add .active to #skeleton-loader
|
||||
add .loading to .component-wrapper in #cv-inner-content-page-1
|
||||
add .loading to .component-wrapper in #cv-inner-content-page-2
|
||||
end
|
||||
|
||||
on htmx:afterSwap from #language-selector
|
||||
wait 100ms -- Brief delay to ensure content is rendered
|
||||
remove .active from #skeleton-loader
|
||||
remove .loading from .component-wrapper in #cv-inner-content-page-1
|
||||
remove .loading from .component-wrapper in #cv-inner-content-page-2
|
||||
end
|
||||
```
|
||||
|
||||
**Alternative Approach (Pure HTMX):**
|
||||
Use `hx-indicator` attribute with CSS to control visibility:
|
||||
- `hx-indicator="#skeleton-loader"` on language buttons
|
||||
- HTMX automatically adds `.htmx-request` class during requests
|
||||
- CSS: `#skeleton-loader.htmx-request { opacity: 1; }`
|
||||
**Alternative Approach (CSS-based):**
|
||||
Use HTMX's automatic class management:
|
||||
- Add `.component-wrapper` to elements receiving OOB swaps
|
||||
- Use HTMX classes: `.htmx-swapping` triggers skeleton state
|
||||
- CSS: `.component-wrapper.htmx-swapping .actual-content { opacity: 0; }`
|
||||
- CSS: `.component-wrapper.htmx-swapping .skeleton-content { opacity: 1; }`
|
||||
|
||||
**Step 6: Content Fade Transitions**
|
||||
|
||||
@@ -210,13 +228,15 @@ Add fade-in/out to actual content sections:
|
||||
```
|
||||
|
||||
**What to Prioritize:**
|
||||
1. Get basic skeleton structure showing/hiding correctly
|
||||
2. Add pulsing animation
|
||||
3. Refine skeleton shapes to better match layout
|
||||
4. Polish timing and transitions
|
||||
5. Add accessibility features
|
||||
1. Add skeleton markup inside each existing component (dual-state structure)
|
||||
2. Implement CSS toggling between actual content and skeleton content
|
||||
3. Add pulsing animation to skeleton elements
|
||||
4. Refine skeleton shapes to better match layout
|
||||
5. Polish timing and transitions
|
||||
6. Add accessibility features
|
||||
|
||||
**What to Avoid:**
|
||||
- Don't create a separate overlay layer - skeleton states live inside components
|
||||
- Don't create overly complex skeleton markup - simple boxes are fine
|
||||
- Don't make the skeleton identical to real content - approximate is better
|
||||
- Don't use JavaScript animations - stick to CSS for performance
|
||||
@@ -233,22 +253,23 @@ Add fade-in/out to actual content sections:
|
||||
<output>
|
||||
Create/modify the following files:
|
||||
|
||||
1. **`./templates/partials/skeleton-loader.html`** (NEW)
|
||||
- Skeleton loader HTML structure
|
||||
- Simplified CV layout with placeholder boxes
|
||||
- Should mirror the structure of CV content sections
|
||||
1. **Modify existing component templates** (UPDATE)
|
||||
- `./templates/partials/cv-header.html` - Add skeleton state inside component
|
||||
- `./templates/partials/skills-*.html` - Add skeleton placeholders
|
||||
- `./templates/partials/experience-entry.html` - Add skeleton placeholders
|
||||
- Each component gets dual-state structure (actual content + skeleton content)
|
||||
|
||||
2. **`./static/css/skeleton.css`** (NEW)
|
||||
- Skeleton loader styles
|
||||
- Pulsing animation keyframes
|
||||
- Skeleton overlay positioning and transitions
|
||||
- Component state toggling styles (`.loading` class behavior)
|
||||
- Responsive skeleton layouts
|
||||
- Accessibility overrides for `prefers-reduced-motion`
|
||||
|
||||
3. **`./templates/partials/navigation/language-selector.html`**
|
||||
- Add HTMX swap timing modifiers
|
||||
- Add skeleton loader indicator reference
|
||||
- Add hyperscript for skeleton show/hide events
|
||||
- Add hyperscript to toggle `.loading` class on component wrappers
|
||||
- Coordinate skeleton state transitions with HTMX events
|
||||
|
||||
4. **`./templates/language-switch.html`**
|
||||
- May need to coordinate OOB swap timing
|
||||
@@ -259,10 +280,10 @@ Create/modify the following files:
|
||||
- Import skeleton.css if created separately
|
||||
- Add HTMX animation class styles
|
||||
|
||||
6. **Include skeleton loader in main template** (wherever CV content lives)
|
||||
- Add `<div id="skeleton-loader" class="skeleton-overlay">...</div>`
|
||||
- Position over content area
|
||||
- Initially hidden, shown during language switch
|
||||
6. **Ensure component wrappers are properly structured**
|
||||
- Each component should have `.component-wrapper` class
|
||||
- Components contain both `.actual-content` and `.skeleton-content`
|
||||
- Skeleton content is hidden by default, shown when `.loading` class is added
|
||||
|
||||
</output>
|
||||
|
||||
@@ -270,10 +291,11 @@ Create/modify the following files:
|
||||
Before declaring complete, perform these tests:
|
||||
|
||||
**1. Visual Verification:**
|
||||
- [ ] Click EN button: Content fades out → Skeleton appears → New content fades in
|
||||
- [ ] Click EN button: Content fades out → Skeleton appears inside components → New content fades in
|
||||
- [ ] Click ES button: Same smooth transition with skeleton
|
||||
- [ ] Skeleton boxes pulse/shimmer smoothly
|
||||
- [ ] Skeleton boxes pulse/shimmer smoothly inside each component
|
||||
- [ ] Skeleton roughly matches CV layout (recognizable structure)
|
||||
- [ ] Each component toggles between actual content and skeleton state
|
||||
- [ ] No flashing or jarring jumps during transition
|
||||
|
||||
**2. Timing Verification:**
|
||||
@@ -314,7 +336,8 @@ Before declaring complete, perform these tests:
|
||||
- [ ] Page refresh during skeleton display - recovers gracefully
|
||||
|
||||
**Success Indicators:**
|
||||
✅ Skeleton loaders appear during language transitions
|
||||
✅ Components toggle between actual content and skeleton states during language transitions
|
||||
✅ Skeleton states appear INSIDE each component (not as separate overlay)
|
||||
✅ Pulsing animation is smooth and subtle
|
||||
✅ Total transition time feels professional (500-700ms)
|
||||
✅ No jarring content jumps or flashes
|
||||
@@ -324,16 +347,17 @@ Before declaring complete, perform these tests:
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
1. Skeleton loaders with pulsing animation appear during language switching
|
||||
2. Three-phase transition: fade-out → skeleton → fade-in
|
||||
3. Total transition time: 500-700ms (feels premium, not sluggish)
|
||||
4. Skeleton structure roughly matches CV layout (recognizable)
|
||||
5. Animations are GPU-accelerated and buttery smooth (60fps)
|
||||
6. Respects `prefers-reduced-motion` accessibility setting
|
||||
7. Handles rapid clicking without breaking or visual glitches
|
||||
8. Works consistently across modern browsers and device sizes
|
||||
9. Code follows existing project patterns and conventions
|
||||
10. Implementation is maintainable and doesn't overcomplicate the codebase
|
||||
1. Each CV component toggles between actual content and skeleton state during language switching
|
||||
2. Skeleton loaders with pulsing animation appear INSIDE components (not as separate overlay)
|
||||
3. Three-phase transition: fade-out → skeleton → fade-in
|
||||
4. Total transition time: 500-700ms (feels premium, not sluggish)
|
||||
5. Skeleton structure roughly matches CV layout (recognizable)
|
||||
6. Animations are GPU-accelerated and buttery smooth (60fps)
|
||||
7. Respects `prefers-reduced-motion` accessibility setting
|
||||
8. Handles rapid clicking without breaking or visual glitches
|
||||
9. Works consistently across modern browsers and device sizes
|
||||
10. Code follows existing project patterns and conventions
|
||||
11. Implementation is maintainable and doesn't overcomplicate the codebase
|
||||
</success_criteria>
|
||||
|
||||
<references>
|
||||
|
||||
Reference in New Issue
Block a user