03-03: Workout Experience Polish - enhanced exercise cards, progress badges, rest timer, KLART button, warmup styling
This commit is contained in:
@@ -0,0 +1,64 @@
|
|||||||
|
# Plan 03-02: Dashboard Polish
|
||||||
|
|
||||||
|
**Goal:** Transform dashboard from "functional but plain" to polished, enterprise-grade experience
|
||||||
|
|
||||||
|
## Current Issues
|
||||||
|
|
||||||
|
1. **Header** - Basic brand title, no logo mark like auth pages
|
||||||
|
2. **Stat cards** - Plain boxes, no depth or premium feel
|
||||||
|
3. **Calendar** - Functional but lacks visual polish
|
||||||
|
4. **Coach section** - Avatar icon looks basic, message bubble plain
|
||||||
|
5. **Today's workout card** - Needs better visual weight and polish
|
||||||
|
6. **Spacing rhythm** - Inconsistent paddings/margins throughout
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
### Files to Modify
|
||||||
|
|
||||||
|
- frontend/src/pages/Dashboard.jsx
|
||||||
|
- frontend/src/App.css (dashboard section)
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
**1. Header Branding**
|
||||||
|
- Replace "Gravl" text with Logo component (reuse from LoginPage)
|
||||||
|
- Add gradient text or subtle brand treatment
|
||||||
|
- Better nav button styling with active states
|
||||||
|
|
||||||
|
**2. Stat Cards Enhancement**
|
||||||
|
- Gradient backgrounds or subtle depth
|
||||||
|
- Better number typography (larger, bolder)
|
||||||
|
- Icons with color accents
|
||||||
|
- Improved spacing and hover states
|
||||||
|
|
||||||
|
**3. Calendar Polish**
|
||||||
|
- Today highlight with brand color
|
||||||
|
- Better day cell sizing and spacing
|
||||||
|
- Subtle shadows on workout days
|
||||||
|
- Smoother transitions
|
||||||
|
|
||||||
|
**4. Coach Section**
|
||||||
|
- Better avatar styling (circle with gradient bg)
|
||||||
|
- Message bubble with subtle background
|
||||||
|
- Improved typography hierarchy
|
||||||
|
|
||||||
|
**5. Today's Workout Card**
|
||||||
|
- Full-width card with improved styling
|
||||||
|
- Better exercise count/time display
|
||||||
|
- Arrow button with hover animation
|
||||||
|
- Subtle gradient or depth
|
||||||
|
|
||||||
|
**6. CSS Polish**
|
||||||
|
- Consistent section spacing (use --space-* variables)
|
||||||
|
- Improve typography scale
|
||||||
|
- Add subtle animations/transitions
|
||||||
|
- Better mobile touch targets
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
- [ ] Header uses same Logo component as auth pages
|
||||||
|
- [ ] Stat cards feel premium (depth/color/accent)
|
||||||
|
- [ ] Calendar has improved today indicator
|
||||||
|
- [ ] Coach section looks polished and friendly
|
||||||
|
- [ ] Workout card has clear visual hierarchy
|
||||||
|
- [ ] Consistent spacing throughout dashboard
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# Plan 03-03: Workout Experience Polish
|
||||||
|
|
||||||
|
**Goal:** Transform the workout session from "functional" to a polished, motivating experience
|
||||||
|
|
||||||
|
## Current Issues
|
||||||
|
|
||||||
|
1. **Exercise cards** - Plain layout, no visual polish, basic text styling
|
||||||
|
2. **Set logging UX** - Stepper inputs work but lack visual refinement
|
||||||
|
3. **Progress indicators** - Progress badges are basic, no visual hierarchy
|
||||||
|
4. **Warmup section** - Collapsible but visually plain, checklist items lack polish
|
||||||
|
5. **Rest timer** - Functional but doesn't feel integrated or premium
|
||||||
|
6. **Alternative exercise modal** - Just implemented (02-02), needs polish pass
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
### Files to Modify
|
||||||
|
|
||||||
|
- frontend/src/pages/WorkoutPage.jsx
|
||||||
|
- frontend/src/components/AlternativeModal.jsx
|
||||||
|
- frontend/src/App.css (workout section)
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
**1. Exercise Cards Enhancement**
|
||||||
|
- Add subtle card depth/shadow
|
||||||
|
- Better exercise name typography (larger, weight hierarchy)
|
||||||
|
- Muscle group badges with color coding
|
||||||
|
- Improved spacing between elements
|
||||||
|
- Subtle hover/focus states for interactive elements
|
||||||
|
|
||||||
|
**2. Set Logging UX Polish**
|
||||||
|
- Refined stepper input styling (consistent with dashboard buttons)
|
||||||
|
- Better "Log Set" button - more prominent when active
|
||||||
|
- Clearer visual distinction between logged/unlogged sets
|
||||||
|
- Improved checkmark animation on completion
|
||||||
|
|
||||||
|
**3. Progress Indicators**
|
||||||
|
- Premium progress badges (gradient or subtle depth)
|
||||||
|
- Better "All Done" state - celebration micro-interaction
|
||||||
|
- Visual progress bar or completion percentage
|
||||||
|
|
||||||
|
**4. Warmup Section Polish**
|
||||||
|
- Cleaner checklist styling (custom checkboxes)
|
||||||
|
- Better expansion animation
|
||||||
|
- Subtle completion progress indicator
|
||||||
|
|
||||||
|
**5. Rest Timer Enhancement**
|
||||||
|
- Better visual integration with set cards
|
||||||
|
- Circular progress indicator or countdown animation
|
||||||
|
- Brand color accent when timer active
|
||||||
|
- Gentle pulse animation when running
|
||||||
|
|
||||||
|
**6. Alternative Modal Polish**
|
||||||
|
- Consistent styling with other modals
|
||||||
|
- Better exercise card layouts in modal
|
||||||
|
- Hover states for alternative options
|
||||||
|
|
||||||
|
**7. CSS Polish**
|
||||||
|
- Consistent use of CSS variables (--space-*, --radius-*)
|
||||||
|
- Better typography scale for workout context
|
||||||
|
- Subtle animations (card entry, completion)
|
||||||
|
- Mobile-optimized spacing
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
- [ ] Exercise cards have visual depth and hierarchy
|
||||||
|
- [ ] Set logging feels smooth and responsive
|
||||||
|
- [ ] Progress badges look premium
|
||||||
|
- [ ] Warmup section feels motivating, not tedious
|
||||||
|
- [ ] Rest timer is visually integrated
|
||||||
|
- [ ] Alternative modal matches app polish level
|
||||||
|
- [ ] All animations feel smooth (not janky)
|
||||||
|
- [ ] Mobile experience is thumb-friendly
|
||||||
+6
-11
@@ -1,13 +1,8 @@
|
|||||||
{
|
{
|
||||||
"lastRun": "2026-02-28T22:49:00+01:00",
|
"lastRun": "2026-02-28T23:33:00+01:00",
|
||||||
"status": "completed",
|
"status": "in_progress",
|
||||||
"tasksCompleted": [
|
"tasksCompleted": ["emoji-replacement", "alternative-modal", "workout-page-ux-redish", "chat-onboarding", "03-01-login-onboarding-polish", "03-02-dashboard-polish"],
|
||||||
"emoji-replacement",
|
"activeTask": "03-03-workout-experience",
|
||||||
"alternative-modal",
|
"nextTask": null,
|
||||||
"workout-page-ux-redesign",
|
"notes": "Starting 03-03 Workout Experience Polish - spawning frontend agent"
|
||||||
"chat-onboarding",
|
|
||||||
"03-01-login-onboarding-polish"
|
|
||||||
],
|
|
||||||
"currentPhase": "03-design-polish",
|
|
||||||
"notes": "03-01 klar: Logo.jsx med SVG barbell, LoginPage/RegisterPage uppdaterade med logotyp, taglines, index.css polerad med animationer."
|
|
||||||
}
|
}
|
||||||
|
|||||||
+62
-16
@@ -133,7 +133,7 @@
|
|||||||
|
|
||||||
.day-card {
|
.day-card {
|
||||||
background: var(--bg-card);
|
background: var(--bg-card);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
padding: var(--space-4);
|
padding: var(--space-4);
|
||||||
margin-bottom: var(--space-3);
|
margin-bottom: var(--space-3);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -234,7 +234,7 @@
|
|||||||
|
|
||||||
.exercise-card {
|
.exercise-card {
|
||||||
background: var(--bg-card);
|
background: var(--bg-card);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
margin-bottom: var(--space-3);
|
margin-bottom: var(--space-3);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
@@ -459,7 +459,7 @@
|
|||||||
.klart-btn {
|
.klart-btn {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 52px;
|
min-height: 52px;
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -851,7 +851,7 @@
|
|||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
padding: var(--space-4);
|
padding: var(--space-4);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
font-size: var(--font-base);
|
font-size: var(--font-base);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -925,7 +925,7 @@
|
|||||||
|
|
||||||
.stat-card {
|
.stat-card {
|
||||||
background: var(--bg-card);
|
background: var(--bg-card);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
padding: var(--space-4);
|
padding: var(--space-4);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
@@ -990,7 +990,7 @@
|
|||||||
gap: var(--space-4);
|
gap: var(--space-4);
|
||||||
background: var(--bg-card);
|
background: var(--bg-card);
|
||||||
padding: var(--space-4);
|
padding: var(--space-4);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all var(--transition-base);
|
transition: all var(--transition-base);
|
||||||
@@ -1384,7 +1384,7 @@
|
|||||||
.measurement-card {
|
.measurement-card {
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
padding: var(--space-4);
|
padding: var(--space-4);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -1418,7 +1418,7 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: var(--space-4);
|
padding: var(--space-4);
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
}
|
}
|
||||||
|
|
||||||
.strength-exercise {
|
.strength-exercise {
|
||||||
@@ -1445,7 +1445,7 @@
|
|||||||
gap: var(--space-2);
|
gap: var(--space-2);
|
||||||
background: var(--bg-card);
|
background: var(--bg-card);
|
||||||
padding: var(--space-2);
|
padding: var(--space-2);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1666,7 +1666,7 @@
|
|||||||
|
|
||||||
.rest-timer-btn {
|
.rest-timer-btn {
|
||||||
min-height: 48px;
|
min-height: 48px;
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -1888,7 +1888,7 @@
|
|||||||
padding: var(--space-4);
|
padding: var(--space-4);
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border: 2px dashed var(--border);
|
border: 2px dashed var(--border);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: var(--font-sm);
|
font-size: var(--font-sm);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -2502,7 +2502,7 @@
|
|||||||
width: 56px;
|
width: 56px;
|
||||||
height: 56px;
|
height: 56px;
|
||||||
min-width: 56px;
|
min-width: 56px;
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -2583,7 +2583,7 @@
|
|||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
font-size: var(--font-lg);
|
font-size: var(--font-lg);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -2687,7 +2687,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
background: var(--bg-elevated);
|
background: var(--bg-elevated);
|
||||||
border: 1.5px solid var(--border);
|
border: 1.5px solid var(--border);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
padding: var(--space-4) var(--space-5);
|
padding: var(--space-4) var(--space-5);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
font-size: 16px; /* prevents iOS auto-zoom */
|
font-size: 16px; /* prevents iOS auto-zoom */
|
||||||
@@ -2711,7 +2711,7 @@
|
|||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
font-size: var(--font-base);
|
font-size: var(--font-base);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -2860,7 +2860,7 @@
|
|||||||
|
|
||||||
/* ── Calendar day cells: tighter spacing, better font ────── */
|
/* ── Calendar day cells: tighter spacing, better font ────── */
|
||||||
.calendar-day {
|
.calendar-day {
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-xl);
|
||||||
gap: var(--space-1);
|
gap: var(--space-1);
|
||||||
min-height: 64px;
|
min-height: 64px;
|
||||||
}
|
}
|
||||||
@@ -2912,3 +2912,49 @@
|
|||||||
.week-calendar { animation: sectionIn 300ms ease both; }
|
.week-calendar { animation: sectionIn 300ms ease both; }
|
||||||
.coach-section { animation: sectionIn 300ms ease 80ms both; }
|
.coach-section { animation: sectionIn 300ms ease 80ms both; }
|
||||||
.quick-stats { animation: sectionIn 300ms ease 160ms both; }
|
.quick-stats { animation: sectionIn 300ms ease 160ms both; }
|
||||||
|
/* WORKOUT POLISH - 03-03 */
|
||||||
|
.exercise-card { position: relative; }
|
||||||
|
.exercise-card::before {
|
||||||
|
content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px;
|
||||||
|
background: linear-gradient(90deg, var(--accent), #ff8a65); opacity: 0;
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
.exercise-card.expanded::before { opacity: 1; }
|
||||||
|
.exercise-card.all-done::before {
|
||||||
|
background: linear-gradient(90deg, var(--success), #4ade80); opacity: 1;
|
||||||
|
}
|
||||||
|
.exercise-info h3 { font-size: var(--font-lg); font-weight: 700; }
|
||||||
|
.muscle-group {
|
||||||
|
display: inline-block; font-size: var(--font-xs); font-weight: 600;
|
||||||
|
text-transform: uppercase; padding: var(--space-1) var(--space-2);
|
||||||
|
background: var(--bg-tertiary); border-radius: var(--radius-full);
|
||||||
|
}
|
||||||
|
.progress-badge {
|
||||||
|
background: linear-gradient(135deg, var(--bg-secondary), var(--bg-tertiary));
|
||||||
|
}
|
||||||
|
.progress-badge.complete {
|
||||||
|
background: linear-gradient(135deg, var(--success), #16a34a);
|
||||||
|
box-shadow: 0 4px 12px rgba(34, 197, 94, 0.3);
|
||||||
|
}
|
||||||
|
.rest-timer-card {
|
||||||
|
box-shadow: 0 4px 16px rgba(255, 107, 74, 0.1);
|
||||||
|
}
|
||||||
|
.rest-timer-time.running {
|
||||||
|
text-shadow: 0 0 20px rgba(255, 107, 74, 0.4);
|
||||||
|
animation: pulse-timer 1s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes pulse-timer { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.02); } }
|
||||||
|
.klart-btn {
|
||||||
|
background: linear-gradient(135deg, var(--accent), #e85a3c);
|
||||||
|
border-radius: var(--radius-xl);
|
||||||
|
}
|
||||||
|
.klart-btn.done {
|
||||||
|
background: linear-gradient(135deg, var(--success), #16a34a);
|
||||||
|
animation: success-bounce 0.5s ease;
|
||||||
|
}
|
||||||
|
@keyframes success-bounce { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } }
|
||||||
|
.warmup-check {
|
||||||
|
width: 22px; height: 22px; border-radius: var(--radius-md);
|
||||||
|
border: 2px solid var(--border); display: flex; align-items: center; justify-content: center;
|
||||||
|
}
|
||||||
|
.warmup-item.done .warmup-check { background: var(--success); border-color: var(--success); color: white; }
|
||||||
|
|||||||
Reference in New Issue
Block a user