765 lines
24 KiB
Markdown
765 lines
24 KiB
Markdown
|
|
# Implement PDF Download Modal with Interactive Thumbnails
|
||
|
|
|
||
|
|
<objective>
|
||
|
|
Transform the existing PDF export modal from a placeholder "work in progress" message into a functional PDF download interface with three interactive thumbnail previews: Short CV, Long CV, and Custom (placeholder). Each thumbnail will show a stylized representation of the CV option using skeleton/placeholder styling, allowing users to visually preview and select their preferred download format.
|
||
|
|
|
||
|
|
**Key Goals:**
|
||
|
|
1. Repurpose the existing `pdf-modal.html` dialog to show three CV format options
|
||
|
|
2. Create thumbnail cards that represent each option visually
|
||
|
|
3. Use skeleton/placeholder styling (similar to animated placeholders) for visual representation
|
||
|
|
4. Make thumbnails interactive - click to select, visual highlight on selection
|
||
|
|
5. Prepare foundation for PDF download functionality (actual download in future phase)
|
||
|
|
|
||
|
|
**Why This Matters:**
|
||
|
|
- Visual choice is easier than text: Users can see what they'll get before downloading
|
||
|
|
- Professional UX: Modern download interfaces show previews (e.g., Canva, Figma exports)
|
||
|
|
- Sets up extensibility: Foundation for future customization wizard
|
||
|
|
- Reduces user errors: Clear visual indication prevents downloading wrong format
|
||
|
|
</objective>
|
||
|
|
|
||
|
|
<context>
|
||
|
|
**Current State:**
|
||
|
|
- Existing PDF modal at `templates/partials/modals/pdf-modal.html` shows "work in progress" message
|
||
|
|
- Modal uses native `<dialog>` element with hyperscript for interactions
|
||
|
|
- Modal structure follows pattern from `shortcuts-modal.html` (header, body, close button)
|
||
|
|
- No PDF download functionality currently exists
|
||
|
|
|
||
|
|
**Desired Implementation:**
|
||
|
|
|
||
|
|
**Three CV Format Options:**
|
||
|
|
1. **Short CV** - One-page condensed version
|
||
|
|
- Thumbnail shows simplified, compact layout representation
|
||
|
|
- Essential info only (like current `.cv-short` class)
|
||
|
|
|
||
|
|
2. **Long CV** - Full two-page detailed version
|
||
|
|
- Thumbnail shows more detailed layout representation
|
||
|
|
- All sections included (like current `.cv-long` class)
|
||
|
|
|
||
|
|
3. **Custom** - User-configurable version (placeholder for future)
|
||
|
|
- Thumbnail shows question mark or customization icon
|
||
|
|
- Indicates "customize your CV" option
|
||
|
|
- For now, just placeholder - implementation deferred to next phase
|
||
|
|
|
||
|
|
**Thumbnail Design (Hybrid Approach):**
|
||
|
|
- Not full miniature renders (too heavy), not pure skeleton boxes (too abstract)
|
||
|
|
- Stylized representations that are recognizable as CV layouts
|
||
|
|
- Use skeleton/placeholder aesthetic: rounded boxes with subtle gradients
|
||
|
|
- Short version: Single compact card showing header + 2-3 content sections
|
||
|
|
- Long version: Taller card or two cards showing header + 4-6 content sections
|
||
|
|
- Custom version: Card with large question mark or settings icon
|
||
|
|
|
||
|
|
**Interaction Pattern:**
|
||
|
|
- Click thumbnail card to select it (not hover-only)
|
||
|
|
- Selected card gets visual highlight (border, shadow, checkmark badge)
|
||
|
|
- Only one selection at a time (radio button behavior)
|
||
|
|
- "Download PDF" button at bottom (initially disabled until selection made)
|
||
|
|
- Button triggers download of selected format (stub for now, implement later)
|
||
|
|
|
||
|
|
**Reference Files:**
|
||
|
|
@templates/partials/modals/pdf-modal.html - Current modal to transform
|
||
|
|
@templates/partials/modals/shortcuts-modal.html - Modal pattern reference
|
||
|
|
@prompts/002-animate-language-transitions.md - Skeleton loader CSS reference
|
||
|
|
|
||
|
|
**Tech Stack:**
|
||
|
|
- Native HTML `<dialog>` element (already in use)
|
||
|
|
- Hyperscript for interactions (click handlers, state management)
|
||
|
|
- CSS for thumbnail styling (skeleton gradient animations)
|
||
|
|
- Iconify icons for visual indicators
|
||
|
|
</context>
|
||
|
|
|
||
|
|
<requirements>
|
||
|
|
|
||
|
|
## 1. Modal Structure Redesign
|
||
|
|
|
||
|
|
**Update PDF Modal Layout:**
|
||
|
|
```html
|
||
|
|
<dialog id="pdf-modal" class="info-modal pdf-download-modal">
|
||
|
|
<div class="info-modal-content">
|
||
|
|
<!-- Close button (keep existing pattern) -->
|
||
|
|
<button class="info-modal-close">...</button>
|
||
|
|
|
||
|
|
<!-- Header -->
|
||
|
|
<div class="info-modal-header">
|
||
|
|
<h2>Download PDF</h2>
|
||
|
|
<p class="subtitle">Choose your preferred CV format</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Body: Three thumbnail cards -->
|
||
|
|
<div class="pdf-options-grid">
|
||
|
|
<!-- Short CV Card -->
|
||
|
|
<div class="pdf-option-card" data-cv-format="short">
|
||
|
|
<div class="pdf-thumbnail thumbnail-short">
|
||
|
|
<!-- Stylized short CV representation -->
|
||
|
|
</div>
|
||
|
|
<div class="pdf-option-info">
|
||
|
|
<h3>Short CV</h3>
|
||
|
|
<p>One page, essential info</p>
|
||
|
|
</div>
|
||
|
|
<div class="pdf-option-badge">
|
||
|
|
<iconify-icon icon="mdi:check-circle"></iconify-icon>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Long CV Card -->
|
||
|
|
<div class="pdf-option-card" data-cv-format="long">
|
||
|
|
<div class="pdf-thumbnail thumbnail-long">
|
||
|
|
<!-- Stylized long CV representation -->
|
||
|
|
</div>
|
||
|
|
<div class="pdf-option-info">
|
||
|
|
<h3>Long CV</h3>
|
||
|
|
<p>Full version, all details</p>
|
||
|
|
</div>
|
||
|
|
<div class="pdf-option-badge">
|
||
|
|
<iconify-icon icon="mdi:check-circle"></iconify-icon>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Custom CV Card (placeholder) -->
|
||
|
|
<div class="pdf-option-card" data-cv-format="custom">
|
||
|
|
<div class="pdf-thumbnail thumbnail-custom">
|
||
|
|
<!-- Question mark or customize icon -->
|
||
|
|
</div>
|
||
|
|
<div class="pdf-option-info">
|
||
|
|
<h3>Custom</h3>
|
||
|
|
<p>Customize sections</p>
|
||
|
|
</div>
|
||
|
|
<div class="pdf-option-badge">
|
||
|
|
<iconify-icon icon="mdi:check-circle"></iconify-icon>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Footer: Download button -->
|
||
|
|
<div class="pdf-modal-footer">
|
||
|
|
<button class="pdf-download-btn" disabled>
|
||
|
|
<iconify-icon icon="mdi:download"></iconify-icon>
|
||
|
|
Download PDF
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</dialog>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Grid Layout:**
|
||
|
|
- Three columns on desktop (≥768px)
|
||
|
|
- Single column on mobile (<768px) with cards stacked
|
||
|
|
- Equal height cards for visual consistency
|
||
|
|
- Adequate spacing between cards (16-24px gap)
|
||
|
|
|
||
|
|
## 2. Thumbnail Visual Design
|
||
|
|
|
||
|
|
**Skeleton/Placeholder Aesthetic:**
|
||
|
|
|
||
|
|
Use the skeleton loader pattern from prompt 002 to create stylized CV representations:
|
||
|
|
|
||
|
|
```css
|
||
|
|
/* Base thumbnail container */
|
||
|
|
.pdf-thumbnail {
|
||
|
|
background: #ffffff;
|
||
|
|
border: 1px solid #e0e0e0;
|
||
|
|
border-radius: 8px;
|
||
|
|
padding: 16px;
|
||
|
|
height: 280px; /* Adjust based on content */
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
gap: 12px;
|
||
|
|
position: relative;
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Skeleton elements inside thumbnails */
|
||
|
|
.skeleton-block {
|
||
|
|
background: linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%);
|
||
|
|
background-size: 200% 100%;
|
||
|
|
animation: skeleton-shimmer 2s ease-in-out infinite;
|
||
|
|
border-radius: 4px;
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes skeleton-shimmer {
|
||
|
|
0%, 100% { background-position: 200% 0; }
|
||
|
|
50% { background-position: 0 0; }
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Short CV Thumbnail Structure:**
|
||
|
|
```html
|
||
|
|
<div class="pdf-thumbnail thumbnail-short">
|
||
|
|
<!-- Header representation -->
|
||
|
|
<div class="skeleton-block" style="height: 48px;"></div>
|
||
|
|
|
||
|
|
<!-- Content sections (compact) -->
|
||
|
|
<div class="skeleton-block" style="height: 60px;"></div>
|
||
|
|
<div class="skeleton-block" style="height: 60px;"></div>
|
||
|
|
<div class="skeleton-block" style="height: 60px;"></div>
|
||
|
|
|
||
|
|
<!-- Badge overlay -->
|
||
|
|
<div class="thumbnail-badge">1 Page</div>
|
||
|
|
</div>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Long CV Thumbnail Structure:**
|
||
|
|
```html
|
||
|
|
<div class="pdf-thumbnail thumbnail-long">
|
||
|
|
<!-- Header representation -->
|
||
|
|
<div class="skeleton-block" style="height: 48px;"></div>
|
||
|
|
|
||
|
|
<!-- More content sections (detailed) -->
|
||
|
|
<div class="skeleton-block" style="height: 40px;"></div>
|
||
|
|
<div class="skeleton-block" style="height: 40px;"></div>
|
||
|
|
<div class="skeleton-block" style="height: 40px;"></div>
|
||
|
|
<div class="skeleton-block" style="height: 40px;"></div>
|
||
|
|
<div class="skeleton-block" style="height: 40px;"></div>
|
||
|
|
|
||
|
|
<!-- Badge overlay -->
|
||
|
|
<div class="thumbnail-badge">2 Pages</div>
|
||
|
|
</div>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Custom CV Thumbnail Structure:**
|
||
|
|
```html
|
||
|
|
<div class="pdf-thumbnail thumbnail-custom">
|
||
|
|
<!-- Centered icon instead of skeleton blocks -->
|
||
|
|
<div class="custom-placeholder">
|
||
|
|
<iconify-icon icon="mdi:help-circle-outline" width="80" height="80"></iconify-icon>
|
||
|
|
<p>Customize</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Badge overlay -->
|
||
|
|
<div class="thumbnail-badge">Coming Soon</div>
|
||
|
|
</div>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Visual Distinctions:**
|
||
|
|
- Short thumbnail: Fewer, larger blocks (compact feel)
|
||
|
|
- Long thumbnail: More, smaller blocks (detailed feel)
|
||
|
|
- Custom thumbnail: No skeleton blocks, just icon + text
|
||
|
|
- All thumbnails: Page count or status badge in corner
|
||
|
|
|
||
|
|
## 3. Interactive Selection Behavior
|
||
|
|
|
||
|
|
**Click to Select Pattern:**
|
||
|
|
|
||
|
|
Use hyperscript to manage selection state:
|
||
|
|
|
||
|
|
```hyperscript
|
||
|
|
-- On each PDF option card
|
||
|
|
on click
|
||
|
|
-- Remove selected class from all cards
|
||
|
|
set cards to .pdf-option-card in #pdf-modal
|
||
|
|
for card in cards
|
||
|
|
remove .selected from card
|
||
|
|
end
|
||
|
|
|
||
|
|
-- Add selected class to clicked card
|
||
|
|
add .selected to me
|
||
|
|
|
||
|
|
-- Enable download button
|
||
|
|
set downloadBtn to .pdf-download-btn in #pdf-modal
|
||
|
|
remove @disabled from downloadBtn
|
||
|
|
|
||
|
|
-- Store selected format for later
|
||
|
|
set :selectedFormat to my @data-cv-format
|
||
|
|
end
|
||
|
|
```
|
||
|
|
|
||
|
|
**CSS Selection States:**
|
||
|
|
|
||
|
|
```css
|
||
|
|
/* Default card state */
|
||
|
|
.pdf-option-card {
|
||
|
|
border: 2px solid transparent;
|
||
|
|
border-radius: 12px;
|
||
|
|
padding: 16px;
|
||
|
|
cursor: pointer;
|
||
|
|
transition: all 250ms ease;
|
||
|
|
position: relative;
|
||
|
|
background: #ffffff;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Hover state */
|
||
|
|
.pdf-option-card:hover {
|
||
|
|
border-color: #e0e0e0;
|
||
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||
|
|
transform: translateY(-2px);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Selected state */
|
||
|
|
.pdf-option-card.selected {
|
||
|
|
border-color: #4caf50; /* or brand color */
|
||
|
|
box-shadow: 0 6px 16px rgba(76, 175, 80, 0.2);
|
||
|
|
background: #f9fff9; /* subtle tint */
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Selected badge (checkmark) */
|
||
|
|
.pdf-option-badge {
|
||
|
|
position: absolute;
|
||
|
|
top: 8px;
|
||
|
|
right: 8px;
|
||
|
|
opacity: 0;
|
||
|
|
transform: scale(0.8);
|
||
|
|
transition: all 250ms ease;
|
||
|
|
color: #4caf50;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pdf-option-card.selected .pdf-option-badge {
|
||
|
|
opacity: 1;
|
||
|
|
transform: scale(1);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Download Button State:**
|
||
|
|
|
||
|
|
```css
|
||
|
|
/* Disabled state (default) */
|
||
|
|
.pdf-download-btn:disabled {
|
||
|
|
background: #e0e0e0;
|
||
|
|
color: #999999;
|
||
|
|
cursor: not-allowed;
|
||
|
|
opacity: 0.6;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Enabled state (after selection) */
|
||
|
|
.pdf-download-btn:not(:disabled) {
|
||
|
|
background: #4caf50;
|
||
|
|
color: white;
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pdf-download-btn:not(:disabled):hover {
|
||
|
|
background: #45a049;
|
||
|
|
box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 4. Multilingual Support
|
||
|
|
|
||
|
|
**Update Template with Language Conditionals:**
|
||
|
|
|
||
|
|
```html
|
||
|
|
<h2>{{if eq .Lang "es"}}Descargar PDF{{else}}Download PDF{{end}}</h2>
|
||
|
|
<p class="subtitle">
|
||
|
|
{{if eq .Lang "es"}}Elige tu formato preferido{{else}}Choose your preferred format{{end}}
|
||
|
|
</p>
|
||
|
|
|
||
|
|
<!-- Short CV Card -->
|
||
|
|
<h3>{{if eq .Lang "es"}}CV Corto{{else}}Short CV{{end}}</h3>
|
||
|
|
<p>{{if eq .Lang "es"}}Una página, información esencial{{else}}One page, essential info{{end}}</p>
|
||
|
|
|
||
|
|
<!-- Long CV Card -->
|
||
|
|
<h3>{{if eq .Lang "es"}}CV Completo{{else}}Long CV{{end}}</h3>
|
||
|
|
<p>{{if eq .Lang "es"}}Versión completa, todos los detalles{{else}}Full version, all details{{end}}</p>
|
||
|
|
|
||
|
|
<!-- Custom CV Card -->
|
||
|
|
<h3>{{if eq .Lang "es"}}Personalizado{{else}}Custom{{end}}</h3>
|
||
|
|
<p>{{if eq .Lang "es"}}Personaliza secciones{{else}}Customize sections{{end}}</p>
|
||
|
|
|
||
|
|
<!-- Download Button -->
|
||
|
|
<button class="pdf-download-btn" disabled>
|
||
|
|
<iconify-icon icon="mdi:download"></iconify-icon>
|
||
|
|
{{if eq .Lang "es"}}Descargar PDF{{else}}Download PDF{{end}}
|
||
|
|
</button>
|
||
|
|
```
|
||
|
|
|
||
|
|
## 5. Responsive Design
|
||
|
|
|
||
|
|
**Mobile Optimizations:**
|
||
|
|
|
||
|
|
```css
|
||
|
|
/* Desktop: Three columns */
|
||
|
|
@media (min-width: 768px) {
|
||
|
|
.pdf-options-grid {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(3, 1fr);
|
||
|
|
gap: 24px;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Tablet: Two columns */
|
||
|
|
@media (min-width: 480px) and (max-width: 767px) {
|
||
|
|
.pdf-options-grid {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(2, 1fr);
|
||
|
|
gap: 16px;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Custom card spans full width */
|
||
|
|
.pdf-option-card[data-cv-format="custom"] {
|
||
|
|
grid-column: 1 / -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Mobile: Single column */
|
||
|
|
@media (max-width: 479px) {
|
||
|
|
.pdf-options-grid {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
gap: 16px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pdf-thumbnail {
|
||
|
|
height: 200px; /* Shorter on mobile */
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 6. Accessibility
|
||
|
|
|
||
|
|
**ARIA Attributes:**
|
||
|
|
|
||
|
|
```html
|
||
|
|
<div class="pdf-option-card"
|
||
|
|
data-cv-format="short"
|
||
|
|
role="radio"
|
||
|
|
aria-checked="false"
|
||
|
|
aria-label="Short CV - One page, essential information"
|
||
|
|
tabindex="0">
|
||
|
|
...
|
||
|
|
</div>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Keyboard Navigation:**
|
||
|
|
|
||
|
|
```hyperscript
|
||
|
|
-- On PDF option cards
|
||
|
|
on keydown
|
||
|
|
if event.key is 'Enter' or event.key is ' '
|
||
|
|
halt the event
|
||
|
|
trigger click on me
|
||
|
|
end
|
||
|
|
end
|
||
|
|
```
|
||
|
|
|
||
|
|
**Screen Reader Announcements:**
|
||
|
|
|
||
|
|
```html
|
||
|
|
<div class="sr-only" aria-live="polite" id="selection-announcement"></div>
|
||
|
|
|
||
|
|
<!-- Update on selection -->
|
||
|
|
<script>
|
||
|
|
document.getElementById('selection-announcement').textContent =
|
||
|
|
'Selected: Short CV - One page format';
|
||
|
|
</script>
|
||
|
|
```
|
||
|
|
|
||
|
|
## 7. PDF Download Stub (Future Implementation)
|
||
|
|
|
||
|
|
**For Now:**
|
||
|
|
- Download button triggers a function that logs selected format
|
||
|
|
- Shows a toast/alert: "PDF download coming soon!"
|
||
|
|
- Stores selection in variable for when backend is ready
|
||
|
|
|
||
|
|
**Hyperscript Stub:**
|
||
|
|
|
||
|
|
```hyperscript
|
||
|
|
-- On download button
|
||
|
|
on click
|
||
|
|
if :selectedFormat is not null
|
||
|
|
log 'Download requested for format:', :selectedFormat
|
||
|
|
-- TODO: Trigger actual PDF download when backend ready
|
||
|
|
call alert('PDF download coming soon! Selected format: ' + :selectedFormat)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
```
|
||
|
|
|
||
|
|
**Preparation for Real Implementation:**
|
||
|
|
- Format selection stored in `:selectedFormat` variable
|
||
|
|
- Can easily be sent to backend: `hx-get="/download-pdf?format={format}"`
|
||
|
|
- Modal can stay open or close after download
|
||
|
|
- Consider adding loading spinner during download
|
||
|
|
|
||
|
|
</requirements>
|
||
|
|
|
||
|
|
<implementation>
|
||
|
|
|
||
|
|
## Step-by-Step Implementation Plan
|
||
|
|
|
||
|
|
### Phase 1: Update PDF Modal Structure
|
||
|
|
|
||
|
|
1. **Modify `templates/partials/modals/pdf-modal.html`:**
|
||
|
|
- Remove "work in progress" placeholder content
|
||
|
|
- Add new modal structure with header, options grid, footer
|
||
|
|
- Include multilingual text with `{{if eq .Lang}}` conditionals
|
||
|
|
- Add close button (keep existing pattern)
|
||
|
|
|
||
|
|
2. **Create Thumbnail HTML Structures:**
|
||
|
|
- Short CV thumbnail with 3-4 skeleton blocks
|
||
|
|
- Long CV thumbnail with 5-6 skeleton blocks
|
||
|
|
- Custom CV thumbnail with centered icon
|
||
|
|
- Add page count badges to each thumbnail
|
||
|
|
|
||
|
|
### Phase 2: Create CSS Styles
|
||
|
|
|
||
|
|
1. **Add Modal Layout Styles to `static/css/main.css`:**
|
||
|
|
- `.pdf-options-grid` - responsive grid layout
|
||
|
|
- `.pdf-option-card` - card container styles
|
||
|
|
- Card states: default, hover, selected
|
||
|
|
- `.pdf-option-badge` - checkmark badge positioning
|
||
|
|
|
||
|
|
2. **Add Thumbnail Styles:**
|
||
|
|
- `.pdf-thumbnail` - base thumbnail container
|
||
|
|
- `.skeleton-block` - reuse skeleton loader pattern from prompt 002
|
||
|
|
- `@keyframes skeleton-shimmer` - shimmer animation
|
||
|
|
- `.thumbnail-badge` - page count badge overlay
|
||
|
|
- Responsive thumbnail heights
|
||
|
|
|
||
|
|
3. **Add Footer/Button Styles:**
|
||
|
|
- `.pdf-modal-footer` - footer layout
|
||
|
|
- `.pdf-download-btn` - button base styles
|
||
|
|
- Button states: disabled, enabled, hover
|
||
|
|
- Icon + text layout
|
||
|
|
|
||
|
|
### Phase 3: Implement Selection Logic
|
||
|
|
|
||
|
|
1. **Add Hyperscript to Cards:**
|
||
|
|
- Click handler to select card
|
||
|
|
- Remove selection from other cards
|
||
|
|
- Add `.selected` class to clicked card
|
||
|
|
- Store selected format in variable
|
||
|
|
- Enable download button
|
||
|
|
|
||
|
|
2. **Add Keyboard Support:**
|
||
|
|
- Tab navigation between cards
|
||
|
|
- Enter/Space to select card
|
||
|
|
- ESC to close modal (already handled by dialog)
|
||
|
|
|
||
|
|
3. **Add Selection State Management:**
|
||
|
|
- ARIA attributes for screen readers
|
||
|
|
- Visual feedback (border, shadow, badge)
|
||
|
|
- Announcement for screen readers
|
||
|
|
|
||
|
|
### Phase 4: Implement Download Button (Stub)
|
||
|
|
|
||
|
|
1. **Add Click Handler to Download Button:**
|
||
|
|
- Check if format is selected
|
||
|
|
- Log selected format (for debugging)
|
||
|
|
- Show alert/toast: "Coming soon!"
|
||
|
|
- Prepare structure for real implementation
|
||
|
|
|
||
|
|
2. **Prepare for Backend Integration:**
|
||
|
|
- Document expected API endpoint: `/download-pdf?format={format}`
|
||
|
|
- Document expected response: PDF file download
|
||
|
|
- Add TODO comments for future implementation
|
||
|
|
|
||
|
|
### Phase 5: Testing and Refinement
|
||
|
|
|
||
|
|
1. **Visual Testing:**
|
||
|
|
- Three thumbnails display correctly
|
||
|
|
- Skeleton shimmer animations are smooth
|
||
|
|
- Cards respond to hover and selection
|
||
|
|
- Badge appears on selection
|
||
|
|
- Download button enables/disables correctly
|
||
|
|
|
||
|
|
2. **Interaction Testing:**
|
||
|
|
- Click to select works on all three cards
|
||
|
|
- Only one card selected at a time
|
||
|
|
- Download button requires selection
|
||
|
|
- Keyboard navigation works (tab, enter, space)
|
||
|
|
|
||
|
|
3. **Responsive Testing:**
|
||
|
|
- Desktop: Three columns side-by-side
|
||
|
|
- Tablet: Two columns with custom spanning
|
||
|
|
- Mobile: Single column stacked
|
||
|
|
- Thumbnails adapt height appropriately
|
||
|
|
|
||
|
|
4. **Multilingual Testing:**
|
||
|
|
- Switch to Spanish: All text translates
|
||
|
|
- Switch to English: All text translates
|
||
|
|
- No hardcoded text in templates
|
||
|
|
|
||
|
|
**What to Prioritize:**
|
||
|
|
1. Core modal structure and thumbnail layout
|
||
|
|
2. Selection interaction (click to highlight)
|
||
|
|
3. Visual polish (skeleton shimmer, badges)
|
||
|
|
4. Responsive design
|
||
|
|
5. Accessibility features
|
||
|
|
|
||
|
|
**What to Avoid:**
|
||
|
|
- Don't implement actual PDF generation yet (out of scope)
|
||
|
|
- Don't make thumbnails too complex (keep stylized and simple)
|
||
|
|
- Don't use images for thumbnails (pure CSS/HTML)
|
||
|
|
- Don't forget mobile UX (touch targets, stacked layout)
|
||
|
|
- Don't hardcode text (use multilingual template conditionals)
|
||
|
|
|
||
|
|
**Why These Constraints Matter:**
|
||
|
|
- **Stylized over realistic:** Faster to render, easier to maintain, loads instantly
|
||
|
|
- **Skeleton aesthetic:** Consistent with existing placeholder patterns, modern UX
|
||
|
|
- **Interactive selection:** Better UX than radio buttons, visual feedback is immediate
|
||
|
|
- **Stub download:** Allows testing full flow without backend dependency
|
||
|
|
- **Accessibility:** Ensures all users can navigate and select options
|
||
|
|
|
||
|
|
</implementation>
|
||
|
|
|
||
|
|
<output>
|
||
|
|
Modify/create the following files:
|
||
|
|
|
||
|
|
1. **`./templates/partials/modals/pdf-modal.html`**
|
||
|
|
- Transform from placeholder to functional modal
|
||
|
|
- Add three thumbnail cards (short, long, custom)
|
||
|
|
- Add selection interaction with hyperscript
|
||
|
|
- Add download button (stub functionality)
|
||
|
|
- Include multilingual support
|
||
|
|
|
||
|
|
2. **`./static/css/main.css`** (add PDF modal styles section)
|
||
|
|
- Modal layout and grid styles
|
||
|
|
- Card styles (default, hover, selected states)
|
||
|
|
- Thumbnail container and skeleton block styles
|
||
|
|
- Skeleton shimmer animation keyframes
|
||
|
|
- Badge and button styles
|
||
|
|
- Responsive breakpoints
|
||
|
|
|
||
|
|
**Optional:**
|
||
|
|
3. **`./static/css/pdf-modal.css`** (NEW - if you prefer separate file)
|
||
|
|
- Dedicated stylesheet for PDF modal component
|
||
|
|
- Import in main CSS or link in template
|
||
|
|
|
||
|
|
4. **Add UI text to `data/ui-en.json` and `data/ui-es.json`** (if using centralized UI strings)
|
||
|
|
- PDF modal title and subtitle
|
||
|
|
- Option names and descriptions
|
||
|
|
- Button text
|
||
|
|
|
||
|
|
</output>
|
||
|
|
|
||
|
|
<verification>
|
||
|
|
Before declaring complete, perform these comprehensive tests:
|
||
|
|
|
||
|
|
**1. Visual Verification:**
|
||
|
|
- [ ] Modal opens with three thumbnail cards displayed
|
||
|
|
- [ ] Short CV thumbnail shows 3-4 skeleton blocks (compact)
|
||
|
|
- [ ] Long CV thumbnail shows 5-6 skeleton blocks (detailed)
|
||
|
|
- [ ] Custom CV thumbnail shows question mark/icon
|
||
|
|
- [ ] Skeleton blocks have subtle shimmer animation
|
||
|
|
- [ ] Page count badges visible on thumbnails ("1 Page", "2 Pages", "Coming Soon")
|
||
|
|
- [ ] Download button initially disabled (grayed out)
|
||
|
|
|
||
|
|
**2. Selection Interaction:**
|
||
|
|
- [ ] Click Short CV card: Border highlights, checkmark badge appears
|
||
|
|
- [ ] Click Long CV card: Previous selection clears, new card highlights
|
||
|
|
- [ ] Click Custom CV card: Selection transfers correctly
|
||
|
|
- [ ] Only one card selected at any time (radio button behavior)
|
||
|
|
- [ ] Download button enables after selection
|
||
|
|
- [ ] Download button disables if no selection (edge case testing)
|
||
|
|
|
||
|
|
**3. Download Button (Stub):**
|
||
|
|
- [ ] Button disabled when modal first opens
|
||
|
|
- [ ] Button enables after selecting any option
|
||
|
|
- [ ] Click button: Shows "Coming soon" alert (or console log)
|
||
|
|
- [ ] Selected format is stored and retrievable
|
||
|
|
- [ ] Button styling changes between disabled/enabled states
|
||
|
|
|
||
|
|
**4. Responsive Design:**
|
||
|
|
- [ ] Desktop (≥768px): Three columns, equal width
|
||
|
|
- [ ] Tablet (480-767px): Two columns, custom card spans full width
|
||
|
|
- [ ] Mobile (<480px): Single column, cards stacked vertically
|
||
|
|
- [ ] Thumbnails resize appropriately on different screens
|
||
|
|
- [ ] Modal remains centered and scrollable on small screens
|
||
|
|
|
||
|
|
**5. Multilingual Support:**
|
||
|
|
- [ ] English: All text in English
|
||
|
|
- [ ] Spanish: All text in Spanish
|
||
|
|
- [ ] Toggle language: Modal text updates correctly
|
||
|
|
- [ ] No untranslated or hardcoded English text
|
||
|
|
|
||
|
|
**6. Accessibility:**
|
||
|
|
- [ ] Tab navigation: Can tab through all three cards
|
||
|
|
- [ ] Enter key: Selects focused card
|
||
|
|
- [ ] Space key: Selects focused card
|
||
|
|
- [ ] Screen reader: Announces card selection
|
||
|
|
- [ ] ARIA attributes: role="radio", aria-checked updates
|
||
|
|
- [ ] Focus indicators visible on cards
|
||
|
|
- [ ] Download button keyboard accessible
|
||
|
|
|
||
|
|
**7. Animation Performance:**
|
||
|
|
- [ ] Skeleton shimmer is smooth (60fps, no jank)
|
||
|
|
- [ ] Selection transition is smooth (border, shadow appear smoothly)
|
||
|
|
- [ ] Hover effects are responsive (no delay or lag)
|
||
|
|
- [ ] Animations respect `prefers-reduced-motion`
|
||
|
|
|
||
|
|
**8. Modal Behavior:**
|
||
|
|
- [ ] Modal opens when triggered (test trigger button)
|
||
|
|
- [ ] Close button (X) closes modal
|
||
|
|
- [ ] Click outside modal closes it (backdrop click)
|
||
|
|
- [ ] ESC key closes modal
|
||
|
|
- [ ] Selection state persists while modal is open
|
||
|
|
- [ ] Selection resets when modal reopens (or persists - decide which)
|
||
|
|
|
||
|
|
**9. Edge Cases:**
|
||
|
|
- [ ] Rapidly click different cards - no broken states
|
||
|
|
- [ ] Close modal and reopen - state resets correctly
|
||
|
|
- [ ] Switch language while modal open - text updates
|
||
|
|
- [ ] Very long text doesn't break layout (test with Spanish)
|
||
|
|
|
||
|
|
**Success Indicators:**
|
||
|
|
✅ PDF modal transformed from placeholder to functional interface
|
||
|
|
✅ Three thumbnail cards with stylized CV representations
|
||
|
|
✅ Skeleton shimmer animations working smoothly
|
||
|
|
✅ Click-to-select interaction with visual feedback
|
||
|
|
✅ Download button enables/disables based on selection
|
||
|
|
✅ Responsive layout adapts to mobile/tablet/desktop
|
||
|
|
✅ Multilingual support for English and Spanish
|
||
|
|
✅ Keyboard navigation and screen reader support
|
||
|
|
✅ Professional, polished visual design
|
||
|
|
✅ Foundation prepared for future PDF download implementation
|
||
|
|
|
||
|
|
</verification>
|
||
|
|
|
||
|
|
<success_criteria>
|
||
|
|
1. PDF modal displays three interactive thumbnail options
|
||
|
|
2. Thumbnails use skeleton/placeholder styling with shimmer animation
|
||
|
|
3. Short CV thumbnail shows compact layout (fewer blocks)
|
||
|
|
4. Long CV thumbnail shows detailed layout (more blocks)
|
||
|
|
5. Custom CV thumbnail shows placeholder icon/message
|
||
|
|
6. Click-to-select interaction highlights chosen option
|
||
|
|
7. Visual selection feedback: border, shadow, checkmark badge
|
||
|
|
8. Download button enabled only when option selected
|
||
|
|
9. Responsive grid layout: 3 columns desktop, 2 tablet, 1 mobile
|
||
|
|
10. Multilingual support in English and Spanish
|
||
|
|
11. Keyboard accessible with proper ARIA attributes
|
||
|
|
12. Smooth animations (60fps shimmer, 250ms transitions)
|
||
|
|
13. Modal follows existing project patterns (dialog element, hyperscript)
|
||
|
|
14. Code is maintainable and well-documented
|
||
|
|
15. Foundation ready for backend PDF generation integration
|
||
|
|
</success_criteria>
|
||
|
|
|
||
|
|
<research>
|
||
|
|
**Files to Examine:**
|
||
|
|
@templates/partials/modals/pdf-modal.html - Current modal structure
|
||
|
|
@templates/partials/modals/shortcuts-modal.html - Modal pattern reference
|
||
|
|
@prompts/002-animate-language-transitions.md - Skeleton loader CSS pattern
|
||
|
|
@static/css/main.css - Existing modal and skeleton styles
|
||
|
|
|
||
|
|
**Questions to Answer:**
|
||
|
|
1. What skeleton/placeholder styles already exist?
|
||
|
|
2. How are other modals styled (pattern consistency)?
|
||
|
|
3. What multilingual pattern is used for UI text?
|
||
|
|
4. What iconify icons are available for badges/buttons?
|
||
|
|
5. What hyperscript patterns are used elsewhere?
|
||
|
|
</research>
|
||
|
|
|
||
|
|
<additional_notes>
|
||
|
|
**Design Philosophy:**
|
||
|
|
- Stylized over realistic: Faster, lighter, easier to maintain
|
||
|
|
- Progressive disclosure: Show options first, download later
|
||
|
|
- Visual feedback first: Don't make users guess what they selected
|
||
|
|
- Mobile-friendly: Touch targets, stacked layout, clear labels
|
||
|
|
|
||
|
|
**Future Extension Points:**
|
||
|
|
- Custom option will eventually open customization wizard
|
||
|
|
- Download button will trigger server-side PDF generation
|
||
|
|
- Could add "Preview" button to show full-size before download
|
||
|
|
- Could add "Email PDF" option alongside download
|
||
|
|
- Could remember last selection in localStorage
|
||
|
|
|
||
|
|
**Technical Decisions:**
|
||
|
|
- Use skeleton blocks instead of miniature renders (performance)
|
||
|
|
- Use CSS animations instead of JavaScript (smooth, performant)
|
||
|
|
- Use native dialog element (accessibility, browser features)
|
||
|
|
- Use hyperscript for state management (consistent with project)
|
||
|
|
|
||
|
|
**Visual Design Notes:**
|
||
|
|
- Skeleton shimmer should be subtle (not distracting)
|
||
|
|
- Selected state should be obvious (green border + checkmark)
|
||
|
|
- Thumbnails should be recognizable as CV layouts
|
||
|
|
- Cards should feel clickable (cursor, hover effects)
|
||
|
|
- Download button should be prominent when enabled
|
||
|
|
</additional_notes>
|