Card layout improvements for headtohead page
This commit is contained in:
parent
9d4d39058a
commit
76a1f93957
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { songPlayerStore, currentTimeStore, togglePlay, setVolume } from '$lib/stores/songPlayer';
|
import { songPlayerStore, currentTimeStore, togglePlay } from '$lib/stores/songPlayer';
|
||||||
|
|
||||||
export let hash: string;
|
export let hash: string;
|
||||||
export let preferBeatLeader = false;
|
export let preferBeatLeader = false;
|
||||||
@ -11,11 +11,6 @@
|
|||||||
function onToggle() {
|
function onToggle() {
|
||||||
togglePlay(hash, preferBeatLeader);
|
togglePlay(hash, preferBeatLeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onVolumeInput(e: Event) {
|
|
||||||
const v = Number((e.target as HTMLInputElement).value);
|
|
||||||
setVolume(v);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="player">
|
<div class="player">
|
||||||
@ -29,13 +24,6 @@
|
|||||||
<div class="timeline" title="Progress">
|
<div class="timeline" title="Progress">
|
||||||
<div class="progress" style="width: {($songPlayerStore?.currentHash ? (currentTime / ($songPlayerStore?.duration || 1)) : 0) * 100}%"></div>
|
<div class="progress" style="width: {($songPlayerStore?.currentHash ? (currentTime / ($songPlayerStore?.duration || 1)) : 0) * 100}%"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="time">
|
|
||||||
{Math.floor(currentTime / 60)}:{String(Math.floor(currentTime % 60)).padStart(2, '0')} /
|
|
||||||
{Math.floor(($songPlayerStore?.duration || 0) / 60)}:{String(Math.floor(($songPlayerStore?.duration || 0) % 60)).padStart(2, '0')}
|
|
||||||
</div>
|
|
||||||
<div class="volume">
|
|
||||||
<input type="range" min="0" max="1" step="0.01" value={$songPlayerStore?.volume} on:input={onVolumeInput} />
|
|
||||||
</div>
|
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -44,8 +32,6 @@
|
|||||||
.play { width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid rgba(255,255,255,0.15); border-radius: 6px; background: transparent; color: white; cursor: pointer; }
|
.play { width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid rgba(255,255,255,0.15); border-radius: 6px; background: transparent; color: white; cursor: pointer; }
|
||||||
.timeline { flex: 1; height: 6px; background: rgba(255,255,255,0.1); border-radius: 3px; overflow: hidden; }
|
.timeline { flex: 1; height: 6px; background: rgba(255,255,255,0.1); border-radius: 3px; overflow: hidden; }
|
||||||
.progress { height: 100%; background: rgba(255,255,255,0.6); }
|
.progress { height: 100%; background: rgba(255,255,255,0.6); }
|
||||||
.time { font-size: 11px; opacity: 0.8; min-width: 80px; text-align: right; }
|
|
||||||
.volume input { width: 80px; }
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -612,13 +612,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-3 grid grid-cols-2 gap-3 neon-surface">
|
<div class="mt-3 grid grid-cols-2 gap-3 neon-surface">
|
||||||
<div class="player-card playerA {item.accA != null && item.accB != null && item.accA > item.accB ? 'winner' : ''}">
|
<div class="player-card playerA {item.accA != null && item.accB != null && item.accA > item.accB ? 'winner' : ''}">
|
||||||
<div class="label">{idShortA}</div>
|
<div class="label {item.accA != null && item.accB != null && item.accA > item.accB ? 'winner-label' : ''}">{idShortA}</div>
|
||||||
<div class="value {item.accA != null && item.accB != null && (item.accA < item.accB || item.accA === item.accB) ? 'small' : ''}">{item.accA != null ? item.accA.toFixed(2) + '%' : '—'}</div>
|
<div class="value {item.accA != null && item.accB != null && item.accA > item.accB ? 'winner-value' : ''}">{item.accA != null ? item.accA.toFixed(2) + '%' : '—'}</div>
|
||||||
<div class="sub">{item.rankA ? `Rank #${item.rankA}` : ''}</div>
|
<div class="sub">{item.rankA ? `Rank #${item.rankA}` : ''}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="player-card playerB {item.accA != null && item.accB != null && item.accB > item.accA ? 'winner' : ''}">
|
<div class="player-card playerB {item.accA != null && item.accB != null && item.accB > item.accA ? 'winner' : ''}">
|
||||||
<div class="label">{idShortB}</div>
|
<div class="label {item.accA != null && item.accB != null && item.accB > item.accA ? 'winner-label' : ''}">{idShortB}</div>
|
||||||
<div class="value {item.accA != null && item.accB != null && (item.accB < item.accA || item.accA === item.accB) ? 'small' : ''}">{item.accB != null ? item.accB.toFixed(2) + '%' : '—'}</div>
|
<div class="value {item.accA != null && item.accB != null && item.accB > item.accA ? 'winner-value' : ''}">{item.accB != null ? item.accB.toFixed(2) + '%' : '—'}</div>
|
||||||
<div class="sub">{item.rankB ? `Rank #${item.rankB}` : ''}</div>
|
<div class="sub">{item.rankB ? `Rank #${item.rankB}` : ''}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -628,24 +628,26 @@
|
|||||||
<span class="chip chip-draw">Tie</span>
|
<span class="chip chip-draw">Tie</span>
|
||||||
{:else if item.accA > item.accB}
|
{:else if item.accA > item.accB}
|
||||||
<span class="chip chip-win-a">Winner: {idShortA}</span>
|
<span class="chip chip-win-a">Winner: {idShortA}</span>
|
||||||
<span class="ml-2 text-muted">by {(item.accA - item.accB).toFixed(2)}%</span>
|
<span class="ml-2 text-muted margin-text {(item.accA - item.accB) > 1 ? 'margin-bold' : ''} {(item.accA - item.accB) > 2 ? 'margin-bright' : ''}">by {(item.accA - item.accB).toFixed(2)}%</span>
|
||||||
{:else}
|
{:else}
|
||||||
<span class="chip chip-win-b">Winner: {idShortB}</span>
|
<span class="chip chip-win-b">Winner: {idShortB}</span>
|
||||||
<span class="ml-2 text-muted">by {(item.accB - item.accA).toFixed(2)}%</span>
|
<span class="ml-2 text-muted margin-text {(item.accB - item.accA) > 1 ? 'margin-bold' : ''} {(item.accB - item.accA) > 2 ? 'margin-bright' : ''}">by {(item.accB - item.accA).toFixed(2)}%</span>
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<span class="chip">Incomplete</span>
|
<span class="chip">Incomplete</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3">
|
<div class="mt-3 flex items-center gap-2">
|
||||||
<SongPlayer hash={item.hash} preferBeatLeader={true} />
|
<div class="w-1/2">
|
||||||
</div>
|
|
||||||
<div class="mt-3 flex flex-wrap gap-2">
|
|
||||||
<a class="rounded-md border border-white/10 px-2 py-1 text-xs hover:border-white/20" href={item.leaderboardId
|
<a class="rounded-md border border-white/10 px-2 py-1 text-xs hover:border-white/20" href={item.leaderboardId
|
||||||
? `https://beatleader.com/leaderboard/global/${item.leaderboardId}`
|
? `https://beatleader.com/leaderboard/global/${item.leaderboardId}`
|
||||||
: `https://beatleader.com/leaderboard/global/${item.hash}?diff=${encodeURIComponent(item.diffName)}&mode=${encodeURIComponent(item.modeName)}`}
|
: `https://beatleader.com/leaderboard/global/${item.hash}?diff=${encodeURIComponent(item.diffName)}&mode=${encodeURIComponent(item.modeName)}`}
|
||||||
target="_blank" rel="noopener" title="Open in BeatLeader">BL</a>
|
target="_blank" rel="noopener" title="Open in BeatLeader">BL</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="w-1/2">
|
||||||
|
<SongPlayer hash={item.hash} preferBeatLeader={true} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
{/each}
|
{/each}
|
||||||
@ -665,11 +667,6 @@
|
|||||||
.text-danger { color: #dc2626; }
|
.text-danger { color: #dc2626; }
|
||||||
|
|
||||||
/* Cyberpunk neon aesthetics */
|
/* Cyberpunk neon aesthetics */
|
||||||
.neon-frame {
|
|
||||||
background: linear-gradient(135deg, rgba(0,0,0,0.45), rgba(15,15,25,0.65));
|
|
||||||
border: 1px solid rgba(255,255,255,0.08);
|
|
||||||
box-shadow: 0 0 0 1px rgba(0, 255, 204, 0.08) inset, 0 8px 24px rgba(0, 0, 0, 0.5);
|
|
||||||
}
|
|
||||||
.neon-surface {
|
.neon-surface {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
@ -687,21 +684,23 @@
|
|||||||
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
||||||
}
|
}
|
||||||
.player-card.playerA { border-color: rgba(0, 255, 204, 0.25); box-shadow: 0 0 12px rgba(0, 255, 204, 0.08) inset; }
|
.player-card.playerA { border-color: rgba(0, 255, 204, 0.25); box-shadow: 0 0 12px rgba(0, 255, 204, 0.08) inset; }
|
||||||
.player-card.playerB { border-color: rgba(255, 0, 170, 0.25); box-shadow: 0 0 12px rgba(255, 0, 170, 0.08) inset; }
|
.player-card.playerB { border-color: rgba(255, 0, 170, 0.5); box-shadow: 0 0 12px rgba(255, 0, 170, 0.15) inset; }
|
||||||
.player-card:hover {
|
.player-card:hover {
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: 0 10px 24px rgba(0,0,0,0.35);
|
|
||||||
border-color: rgba(0, 255, 204, 0.25);
|
|
||||||
}
|
}
|
||||||
.player-card .label { color: #9ca3af; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; }
|
.player-card .label { color: #9ca3af; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; transition: all 0.2s ease; }
|
||||||
.player-card .value { font-size: 42px; line-height: 1; font-weight: 800; letter-spacing: 0.02em; margin-top: 4px; }
|
.player-card .label.winner-label { color: #ff8800; font-weight: 700; text-shadow: 0 0 8px rgba(255, 136, 0, 0.5); }
|
||||||
.player-card .value.small { font-size: 26px; opacity: 0.8; }
|
.player-card .value { font-size: 26px; line-height: 1; font-weight: 800; letter-spacing: 0.02em; margin-top: 4px; white-space: nowrap; color: #9ca3af; transition: all 0.2s ease; }
|
||||||
.player-card .value, .player-card .value.small { white-space: nowrap; }
|
.player-card .value.winner-value { color: #ffffff; }
|
||||||
.player-card .sub { margin-top: 6px; font-size: 12px; color: #9ca3af; }
|
.player-card .sub { margin-top: 6px; font-size: 12px; color: #9ca3af; }
|
||||||
.player-card.winner {
|
.player-card.playerA.winner {
|
||||||
box-shadow: 0 0 0 1px rgba(0, 255, 204, 0.2) inset, 0 0 18px rgba(0, 255, 204, 0.14);
|
box-shadow: 0 0 0 1px rgba(0, 255, 204, 0.2) inset, 0 0 18px rgba(0, 255, 204, 0.14);
|
||||||
border-color: rgba(0, 255, 204, 0.35);
|
border-color: rgba(0, 255, 204, 0.35);
|
||||||
}
|
}
|
||||||
|
.player-card.playerB.winner {
|
||||||
|
box-shadow: 0 0 0 1px rgba(255, 0, 170, 0.3) inset, 0 0 18px rgba(255, 0, 170, 0.25);
|
||||||
|
border-color: rgba(255, 0, 170, 0.7);
|
||||||
|
}
|
||||||
.chip {
|
.chip {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-radius: 9999px;
|
border-radius: 9999px;
|
||||||
@ -710,10 +709,6 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
background: rgba(255,255,255,0.04);
|
background: rgba(255,255,255,0.04);
|
||||||
}
|
}
|
||||||
.chip-win {
|
|
||||||
border-color: rgba(0, 255, 204, 0.5);
|
|
||||||
background: linear-gradient(90deg, rgba(0, 255, 204, 0.14), rgba(0, 255, 170, 0.08));
|
|
||||||
}
|
|
||||||
.chip-win-a {
|
.chip-win-a {
|
||||||
border-color: rgba(0, 255, 204, 0.5);
|
border-color: rgba(0, 255, 204, 0.5);
|
||||||
background: linear-gradient(90deg, rgba(0, 255, 204, 0.18), rgba(0, 255, 170, 0.10));
|
background: linear-gradient(90deg, rgba(0, 255, 204, 0.18), rgba(0, 255, 170, 0.10));
|
||||||
@ -727,6 +722,10 @@
|
|||||||
background: linear-gradient(90deg, rgba(255, 255, 0, 0.14), rgba(255, 215, 0, 0.08));
|
background: linear-gradient(90deg, rgba(255, 255, 0, 0.14), rgba(255, 215, 0, 0.08));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Margin text styling */
|
||||||
|
.margin-text.margin-bold { font-weight: 700; }
|
||||||
|
.margin-text.margin-bright { color: #ffffff; }
|
||||||
|
|
||||||
/* KPI tiles */
|
/* KPI tiles */
|
||||||
.kpi-tile {
|
.kpi-tile {
|
||||||
border: 1px solid rgba(255,255,255,0.08);
|
border: 1px solid rgba(255,255,255,0.08);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user