style: redesign Match-Cards — balanced layout, better tipped state
- 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:
@@ -77,12 +77,32 @@
|
|||||||
margin-left: auto;
|
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 */
|
/* Match row — Teams + Score */
|
||||||
.matchRow {
|
.matchRow {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 100px 1fr;
|
grid-template-columns: 1fr 40px 1fr;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 8px;
|
||||||
margin-bottom: 18px;
|
margin-bottom: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,6 +362,58 @@
|
|||||||
letter-spacing: 0.05em;
|
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 ──────────────────────────────────── */
|
/* ── State-based card variants ──────────────────────────────────── */
|
||||||
|
|
||||||
.card_open { /* default — no extra styling needed */ }
|
.card_open { /* default — no extra styling needed */ }
|
||||||
|
|||||||
@@ -117,22 +117,28 @@ export default function MatchCard({ match, onTip }: Props) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Kickoff time — above the teams row */}
|
||||||
|
{!isFinished && !isLive && (
|
||||||
|
<div className={styles.kickoffRow}>
|
||||||
|
<span className={styles.kickoffTime}>{formatKickoff(match.utcDate)}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Teams + Score */}
|
{/* Teams + Score */}
|
||||||
<div className={styles.matchRow}>
|
<div className={styles.matchRow}>
|
||||||
{/* Home */}
|
{/* Home */}
|
||||||
<div className={styles.teamHome}>
|
<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} />
|
<FlagBox crest={match.homeTeam.crest} name={match.homeTeam.name} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Score / Kickoff time */}
|
{/* Center: Score or VS separator */}
|
||||||
<div className={styles.scoreBox}>
|
<div className={styles.scoreBox}>
|
||||||
{isFinished || isLive ? (
|
{isFinished || isLive ? (
|
||||||
<div className={styles.scoreStack}>
|
<div className={styles.scoreStack}>
|
||||||
<span className={styles.score}>
|
<span className={styles.score}>
|
||||||
{match.score.home ?? '–'} : {match.score.away ?? '–'}
|
{match.score.home ?? '–'} : {match.score.away ?? '–'}
|
||||||
</span>
|
</span>
|
||||||
{/* For live: show user's tip next to score for comparison */}
|
|
||||||
{isLive && hasTip && (
|
{isLive && hasTip && (
|
||||||
<span className={styles.liveTipCompare}>
|
<span className={styles.liveTipCompare}>
|
||||||
Tipp: {match.userTip!.home}:{match.userTip!.away}
|
Tipp: {match.userTip!.home}:{match.userTip!.away}
|
||||||
@@ -140,16 +146,14 @@ export default function MatchCard({ match, onTip }: Props) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className={styles.kickoffCenter}>
|
<span className={styles.vsSeparator}>:</span>
|
||||||
<span className={styles.kickoffCenterTime}>{formatKickoff(match.utcDate)}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Away */}
|
{/* Away */}
|
||||||
<div className={styles.teamAway}>
|
<div className={styles.teamAway}>
|
||||||
<FlagBox crest={match.awayTeam.crest} name={match.awayTeam.name} />
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -210,22 +214,11 @@ export default function MatchCard({ match, onTip }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
/* ── Tipp vorhanden, noch nicht ausgewertet (tipped state) ── */
|
/* ── Tipp vorhanden, noch nicht ausgewertet (tipped state) ── */
|
||||||
<div className={styles.tipDisplay}>
|
<div className={styles.tippedRow} onClick={match.tippable ? onTip : undefined}>
|
||||||
<div className={styles.tipLeft}>
|
<span className={styles.tippedIcon}>✓</span>
|
||||||
{match.tippable && (
|
<span className={styles.tippedLabel}>Dein Tipp</span>
|
||||||
<button className={styles.changeBtn} onClick={onTip}>Ändern</button>
|
<span className={styles.tippedScore}>{match.userTip!.home} : {match.userTip!.away}</span>
|
||||||
)}
|
{match.tippable && <span className={styles.tippedEdit}>Ändern</span>}
|
||||||
</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>
|
</div>
|
||||||
)
|
)
|
||||||
) : match.tippable ? (
|
) : match.tippable ? (
|
||||||
|
|||||||
Reference in New Issue
Block a user