style: redesign Match-Cards — balanced layout, better tipped state
Build & Deploy Tippspiel / build (push) Successful in 50s

- Move kickoff time above teams row instead of between flags
- Center separator: slim ":" instead of 100px time block
- Use shortName for teams (prevents overflow on mobile)
- Tipped state: clean green bar with icon, label, score, edit hint
  instead of scattered checkmark + underline link

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ronny
2026-04-11 21:29:18 +02:00
parent ede29ac414
commit 3ed70172c7
2 changed files with 90 additions and 25 deletions
+74 -2
View File
@@ -77,12 +77,32 @@
margin-left: auto;
}
/* Kickoff row — above teams */
.kickoffRow {
text-align: center;
margin-bottom: 8px;
}
.kickoffTime {
font-size: 12px;
font-weight: 600;
color: var(--text-secondary);
letter-spacing: 0.03em;
}
/* VS separator */
.vsSeparator {
font-size: 24px;
font-weight: 800;
color: var(--text-muted);
}
/* Match row — Teams + Score */
.matchRow {
display: grid;
grid-template-columns: 1fr 100px 1fr;
grid-template-columns: 1fr 40px 1fr;
align-items: center;
gap: 12px;
gap: 8px;
margin-bottom: 18px;
}
@@ -342,6 +362,58 @@
letter-spacing: 0.05em;
}
/* Tipped row — clean compact display */
.tippedRow {
display: flex;
align-items: center;
gap: 10px;
background: rgba(52, 211, 153, 0.08);
border: 1px solid rgba(52, 211, 153, 0.2);
border-radius: var(--radius-sm);
padding: 10px 14px;
cursor: pointer;
transition: background 0.2s;
}
.tippedRow:hover {
background: rgba(52, 211, 153, 0.14);
}
.tippedIcon {
width: 22px;
height: 22px;
border-radius: 50%;
background: var(--success);
color: white;
font-size: 12px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.tippedLabel {
font-size: 12px;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.04em;
font-weight: 600;
}
.tippedScore {
font-size: 16px;
font-weight: 800;
color: var(--text-primary);
margin-left: auto;
}
.tippedEdit {
font-size: 11px;
color: var(--primary);
font-weight: 600;
opacity: 0.7;
}
/* ── State-based card variants ──────────────────────────────────── */
.card_open { /* default — no extra styling needed */ }
+16 -23
View File
@@ -117,22 +117,28 @@ export default function MatchCard({ match, onTip }: Props) {
)}
</div>
{/* Kickoff time — above the teams row */}
{!isFinished && !isLive && (
<div className={styles.kickoffRow}>
<span className={styles.kickoffTime}>{formatKickoff(match.utcDate)}</span>
</div>
)}
{/* Teams + Score */}
<div className={styles.matchRow}>
{/* Home */}
<div className={styles.teamHome}>
<span className={styles.teamName}>{match.homeTeam.name}</span>
<span className={styles.teamName}>{match.homeTeam.shortName}</span>
<FlagBox crest={match.homeTeam.crest} name={match.homeTeam.name} />
</div>
{/* Score / Kickoff time */}
{/* Center: Score or VS separator */}
<div className={styles.scoreBox}>
{isFinished || isLive ? (
<div className={styles.scoreStack}>
<span className={styles.score}>
{match.score.home ?? ''}&nbsp;:&nbsp;{match.score.away ?? ''}
</span>
{/* For live: show user's tip next to score for comparison */}
{isLive && hasTip && (
<span className={styles.liveTipCompare}>
Tipp: {match.userTip!.home}:{match.userTip!.away}
@@ -140,16 +146,14 @@ export default function MatchCard({ match, onTip }: Props) {
)}
</div>
) : (
<div className={styles.kickoffCenter}>
<span className={styles.kickoffCenterTime}>{formatKickoff(match.utcDate)}</span>
</div>
<span className={styles.vsSeparator}>:</span>
)}
</div>
{/* Away */}
<div className={styles.teamAway}>
<FlagBox crest={match.awayTeam.crest} name={match.awayTeam.name} />
<span className={styles.teamName}>{match.awayTeam.name}</span>
<span className={styles.teamName}>{match.awayTeam.shortName}</span>
</div>
</div>
@@ -210,22 +214,11 @@ export default function MatchCard({ match, onTip }: Props) {
</div>
) : (
/* ── Tipp vorhanden, noch nicht ausgewertet (tipped state) ── */
<div className={styles.tipDisplay}>
<div className={styles.tipLeft}>
{match.tippable && (
<button className={styles.changeBtn} onClick={onTip}>Ändern</button>
)}
</div>
<div className={styles.tipCenter}>
{!match.tippable && <span className={styles.tipLabel}>DEIN TIPP</span>}
<span className={styles.tipDisplay_score}>
<Check size={13} strokeWidth={3} style={{ color: 'var(--success)', flexShrink: 0 }} />
<span className={styles.tipScore}>
{match.userTip!.home} : {match.userTip!.away}
</span>
</span>
</div>
<div className={styles.tipRight} />
<div className={styles.tippedRow} onClick={match.tippable ? onTip : undefined}>
<span className={styles.tippedIcon}></span>
<span className={styles.tippedLabel}>Dein Tipp</span>
<span className={styles.tippedScore}>{match.userTip!.home} : {match.userTip!.away}</span>
{match.tippable && <span className={styles.tippedEdit}>Ändern</span>}
</div>
)
) : match.tippable ? (