Design overhaul: Dark fitness theme, no emojis

CSS:
- Dark background (#0a0a0f, #0d0d12, #15151b)
- Orange accent (#ff6b35)
- Muted text (#a1a1aa, #71717a)
- Inter font from Google Fonts
- Workout type colors (push/pull/legs/etc)

Dashboard:
- Calendar dots are CSS circles, not emoji
- Coach avatar uses SVG icon
- All emojis replaced with Icons.jsx SVGs
- Navigation uses proper icons

WorkoutPage:
- Warmup exercises without emojis
- Check icons instead of emoji checkmarks
- Arrow icons for navigation
- Fire icon for warmup section

Professional fitness app aesthetic inspired by Nike/FITBOD
This commit is contained in:
2026-02-01 19:45:03 +01:00
parent fe5420e9be
commit e629a20cec
5 changed files with 109 additions and 46 deletions
+4 -1
View File
@@ -4,9 +4,12 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="theme-color" content="#1a1a2e" />
<meta name="theme-color" content="#0a0a0f" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<title>Gravl - Träning</title>
</head>
<body>
+40 -14
View File
@@ -461,15 +461,15 @@
}
.coach-avatar {
font-size: 2.5rem;
width: 60px;
height: 60px;
background: rgba(255,255,255,0.2);
width: 52px;
height: 52px;
background: rgba(255,255,255,0.15);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
color: rgba(255,255,255,0.9);
}
.coach-message {
@@ -549,13 +549,6 @@
color: white;
}
.calendar-day.has-workout .day-dot {
color: var(--success);
}
.calendar-day.today .day-dot {
color: white;
}
.day-name {
font-size: 0.7rem;
@@ -574,10 +567,17 @@
}
.day-dot {
font-size: 0.5rem;
width: 4px;
height: 4px;
border-radius: 50%;
background: var(--success);
margin-top: 0.25rem;
}
.calendar-day.today .day-dot {
background: rgba(255,255,255,0.8);
}
/* Today's Workout */
.todays-workout {
display: flex;
@@ -731,6 +731,19 @@
text-transform: uppercase;
}
.stat-icon {
display: flex;
align-items: center;
justify-content: center;
}
/* Brand title with icon */
.brand-title {
display: flex;
align-items: center;
gap: 0.5rem;
}
/* Upcoming Workouts */
.upcoming-workouts h2 {
font-size: 1.1rem;
@@ -818,6 +831,9 @@
font-size: 1rem;
cursor: pointer;
padding: 0.5rem;
display: flex;
align-items: center;
gap: 0.25rem;
}
/* Page Main */
@@ -1242,7 +1258,9 @@
}
.warmup-icon {
font-size: 1.5rem;
display: flex;
align-items: center;
color: var(--accent);
}
.warmup-title h2 {
@@ -1260,7 +1278,8 @@
}
.expand-icon {
font-size: 0.75rem;
display: flex;
align-items: center;
color: var(--text-muted);
transition: transform 0.2s;
}
@@ -1362,6 +1381,10 @@
font-size: 0.95rem;
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.warmup-done-btn:hover {
@@ -1573,6 +1596,9 @@
}
.tip-badge {
display: flex;
align-items: center;
gap: 0.4rem;
background: var(--bg-secondary);
border: 1px solid var(--border);
padding: 0.5rem 0.75rem;
+38 -12
View File
@@ -5,21 +5,43 @@
}
:root {
--bg-primary: #0f0f1a;
--bg-secondary: #1a1a2e;
--bg-card: #16213e;
--bg-card-hover: #1f3460;
--text-primary: #eaeaea;
--text-secondary: #a0a0a0;
--accent: #e94560;
--accent-hover: #ff6b6b;
--success: #4ecca3;
--warning: #ffd93d;
--border: #2a2a4a;
/* Dark fitness palette */
--bg-primary: #0a0a0f;
--bg-secondary: #0d0d12;
--bg-card: #15151b;
--bg-card-hover: #1a1a22;
--bg: #0a0a0f;
/* Text colors */
--text-primary: #ffffff;
--text-secondary: #a1a1aa;
--text-muted: #71717a;
--text: #ffffff;
/* Accent - energetic orange */
--accent: #ff6b35;
--accent-hover: #ff8555;
/* Status colors */
--success: #22c55e;
--warning: #f59e0b;
--error: #ef4444;
/* Border */
--border: #1f1f28;
/* Workout type colors - muted, professional */
--workout-push: #ef4444;
--workout-pull: #3b82f6;
--workout-legs: #22c55e;
--workout-shoulders: #f59e0b;
--workout-upper: #8b5cf6;
--workout-lower: #06b6d4;
--workout-default: #ff6b35;
}
html, body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
min-height: 100vh;
@@ -27,6 +49,10 @@ html, body {
-moz-osx-font-smoothing: grayscale;
}
h1, h2, h3, h4, h5, h6 {
font-weight: 700;
}
#root {
min-height: 100vh;
}
+1 -1
View File
@@ -136,7 +136,7 @@ function Dashboard({ onStartWorkout, onNavigate }) {
>
<span className="day-name">{name}</span>
<span className="day-date">{date.getDate()}</span>
{hasWorkout && <span className="day-dot"></span>}
{hasWorkout && <span className="day-dot" />}
</div>
)
})}
+26 -18
View File
@@ -1,13 +1,14 @@
import { useState, useEffect } from 'react'
import { Icon } from '../components/Icons'
// Uppvärmningsövningar baserat på muskelgrupp
const warmupExercises = {
general: [
{ name: 'Cykel eller roddmaskin', duration: '5 min', icon: '🚴' },
{ name: 'Armcirklar', duration: '30 sek/riktning', icon: '🔄' },
{ name: 'Bensvingar (framåt/bakåt)', duration: '10 per ben', icon: '🦵' },
{ name: 'Bensvingar (sidled)', duration: '10 per ben', icon: '🦵' },
{ name: 'Höftcirklar', duration: '10 per riktning', icon: '⭕' },
{ name: 'Cykel eller roddmaskin', duration: '5 min' },
{ name: 'Armcirklar', duration: '30 sek/riktning' },
{ name: 'Bensvingar (framåt/bakåt)', duration: '10 per ben' },
{ name: 'Bensvingar (sidled)', duration: '10 per ben' },
{ name: 'Höftcirklar', duration: '10 per riktning' },
],
specific: {
'Bröst': [
@@ -97,7 +98,9 @@ function WorkoutPage({ day, week, logs, onLogSet, onBack, fetchProgression }) {
return (
<div className="workout-page">
<header className="page-header">
<button className="back-btn" onClick={onBack}> Tillbaka</button>
<button className="back-btn" onClick={onBack}>
<Icon name="arrowLeft" size={16} /> Tillbaka
</button>
<div className="header-center">
<h1>{day.name}</h1>
<span className="header-subtitle">Vecka {week} Dag {day.day_number}</span>
@@ -123,11 +126,13 @@ function WorkoutPage({ day, week, logs, onLogSet, onBack, fetchProgression }) {
onClick={() => setWarmupExpanded(!warmupExpanded)}
>
<div className="warmup-title">
<span className="warmup-icon">🔥</span>
<span className="warmup-icon"><Icon name="fire" size={20} /></span>
<h2>Uppvärmning</h2>
<span className="warmup-progress">{warmupProgress}/{totalWarmups}</span>
</div>
<span className={`expand-icon ${warmupExpanded ? 'expanded' : ''}`}></span>
<span className={`expand-icon ${warmupExpanded ? 'expanded' : ''}`}>
<Icon name="chevronDown" size={16} />
</span>
</div>
{warmupExpanded && (
@@ -143,9 +148,8 @@ function WorkoutPage({ day, week, logs, onLogSet, onBack, fetchProgression }) {
onClick={() => toggleWarmup(idx)}
>
<span className="warmup-check">
{completedWarmups.has(idx) ? '✓' : ''}
{completedWarmups.has(idx) ? <Icon name="check" size={14} /> : ''}
</span>
<span className="warmup-item-icon">{warmup.icon}</span>
<span className="warmup-name">{warmup.name}</span>
<span className="warmup-duration">{warmup.duration || warmup.reps}</span>
</div>
@@ -167,7 +171,7 @@ function WorkoutPage({ day, week, logs, onLogSet, onBack, fetchProgression }) {
onClick={() => toggleWarmup(globalIdx)}
>
<span className="warmup-check">
{completedWarmups.has(globalIdx) ? '✓' : ''}
{completedWarmups.has(globalIdx) ? <Icon name="check" size={14} /> : ''}
</span>
<span className="warmup-name">{warmup.name}</span>
<span className="warmup-duration">{warmup.reps}</span>
@@ -196,10 +200,10 @@ function WorkoutPage({ day, week, logs, onLogSet, onBack, fetchProgression }) {
}}
>
<span className="warmup-check">
{completedWarmups.has('prep') ? '✓' : ''}
{completedWarmups.has('prep') ? <Icon name="check" size={14} /> : ''}
</span>
<span className="warmup-name">Lätta set {exercises[0].name}</span>
<span className="warmup-duration">2×10 @ 50%</span>
<span className="warmup-duration">2x10 @ 50%</span>
</div>
</div>
</div>
@@ -209,7 +213,11 @@ function WorkoutPage({ day, week, logs, onLogSet, onBack, fetchProgression }) {
className={`warmup-done-btn ${warmupDone ? 'completed' : ''}`}
onClick={() => setWarmupDone(!warmupDone)}
>
{warmupDone ? '✓ Uppvärmning klar!' : 'Markera uppvärmning som klar'}
{warmupDone ? (
<><Icon name="check" size={18} /> Uppvärmning klar</>
) : (
'Markera uppvärmning som klar'
)}
</button>
</div>
)}
@@ -239,7 +247,7 @@ function WorkoutPage({ day, week, logs, onLogSet, onBack, fetchProgression }) {
onClick={onBack}
>
{completedExercises === exercises.length
? '🎉 Avsluta pass'
? 'Avsluta pass'
: `Avsluta pass (${completedExercises}/${exercises.length} klara)`}
</button>
</main>
@@ -302,9 +310,9 @@ function ExerciseCard({ exercise, logs, progression, expanded, onToggle, onLogSe
<div className="exercise-body">
{progression && (
<div className="progression-hint">
💡 {progression.reason}
{progression.reason}
{progression.suggestedWeight && (
<strong> {progression.suggestedWeight} kg</strong>
<strong> {progression.suggestedWeight} kg</strong>
)}
</div>
)}
@@ -338,7 +346,7 @@ function ExerciseCard({ exercise, logs, progression, expanded, onToggle, onLogSe
className={`complete-btn ${input.completed ? 'done' : ''}`}
onClick={() => handleComplete(setNum)}
>
{input.completed ? '✓' : ''}
{input.completed ? <Icon name="check" size={18} /> : ''}
</button>
</div>
)