Use compact player record cards on mobile
This commit is contained in:
@@ -10,6 +10,8 @@
|
||||
import CopyValue from '$ui/components/CopyValue.svelte';
|
||||
import Badge from '$ui/components/primitives/Badge.svelte';
|
||||
import RecordSource from '$ui/components/RecordSource.svelte';
|
||||
import PlayerMapCards from '$ui/components/PlayerMapCards.svelte';
|
||||
import PlayerMatchCards from '$ui/components/PlayerMatchCards.svelte';
|
||||
import EmptyState from '$ui/components/primitives/EmptyState.svelte';
|
||||
|
||||
let { data }: { data: { profile: PlayerProfile; returnTo: string;
|
||||
@@ -101,8 +103,9 @@
|
||||
|
||||
<section class="panel" aria-labelledby="maps-title">
|
||||
<div class="panel-heading"><h2 id="maps-title">Per-map records</h2><p>Personal best rounds and every tracked stat across both games, ordered by highest round.</p></div>
|
||||
<div class="mobile-records"><PlayerMapCards maps={profile.maps} metric={scope.metric} /></div>
|
||||
<!-- svelte-ignore a11y_no_noninteractive_tabindex (Scrollable table for keyboard users.) -->
|
||||
<div class="table-scroll" role="region" aria-label="Per-map player records" tabindex="0">
|
||||
<div class="table-scroll desktop-records" role="region" aria-label="Per-map player records" tabindex="0">
|
||||
<table>
|
||||
<thead><tr><th scope="col">Map</th>{#each playerStatMetrics as metric}<th scope="col">{metric.label}</th>{/each}</tr></thead>
|
||||
<tbody>{#each profile.maps as map (`${map.game}:${map.key}`)}
|
||||
@@ -116,10 +119,11 @@
|
||||
<section class="panel" aria-labelledby="history-title">
|
||||
<div class="panel-heading"><h2 id="history-title">Match history</h2><p>Completed matches in the selected game and map, most recently observed first. Stats reflect this player's participation.</p></div>
|
||||
{#if profile.matches.length}
|
||||
<div class="mobile-records"><PlayerMatchCards matches={profile.matches} /></div>
|
||||
<!-- svelte-ignore a11y_no_noninteractive_tabindex (Scrollable table for keyboard users.) -->
|
||||
<div class="table-scroll" role="region" aria-label="Player match history" tabindex="0">
|
||||
<div class="table-scroll desktop-records" role="region" aria-label="Player match history" tabindex="0">
|
||||
<table>
|
||||
<thead><tr><th scope="col">Map / server</th><th scope="col">Match started</th><th scope="col">Match status</th>{#each historyColumns as key}<th scope="col">{playerStatMetrics.find(metric => metric.key === key)!.label}</th>{/each}</tr></thead>
|
||||
<thead><tr><th scope="col">Map / server</th><th scope="col">First observed</th><th scope="col">Match status</th>{#each historyColumns as key}<th scope="col">{playerStatMetrics.find(metric => metric.key === key)!.label}</th>{/each}</tr></thead>
|
||||
<tbody>{#each profile.matches as match (match.id)}
|
||||
<tr><th scope="row">{#if match.status === 'completed'}<a href={`/matches/${match.id}`} aria-label={`View ${match.mapName} match from ${date(match.startedAt)}`}>{match.mapName}</a>{:else}{match.mapName}{/if}<small>{gameName(match.game)}</small><small>{match.server} {#if match.server_deleted_at}<Badge>Deleted</Badge>{/if}</small></th><td>{date(match.startedAt)}</td>
|
||||
<td class="status">{match.status}<small>{match.completed ? 'Completion credited' : 'No completion credit'}</small></td>
|
||||
@@ -129,7 +133,7 @@
|
||||
</table>
|
||||
</div>
|
||||
<div class="pagination"><span>{number.format(profile.offset + 1)}–{number.format(profile.offset + profile.matches.length)} of {number.format(profile.matchesTotal)} games</span>
|
||||
<div><Button size="sm" href={profileViewHref($page.url, { offset: String(Math.max(0, profile.offset - profile.limit)) })} disabled={profile.offset === 0}>Previous</Button><Button size="sm" href={profileViewHref($page.url, { offset: String(profile.offset + profile.limit) })} disabled={profile.offset + profile.limit >= profile.matchesTotal}>Next</Button></div>
|
||||
<div><Button size="sm" href={`${profileViewHref($page.url, { offset: String(Math.max(0, profile.offset - profile.limit)) })}#history-title`} disabled={profile.offset === 0}>Previous</Button><Button size="sm" href={`${profileViewHref($page.url, { offset: String(profile.offset + profile.limit) })}#history-title`} disabled={profile.offset + profile.limit >= profile.matchesTotal}>Next</Button></div>
|
||||
</div>
|
||||
{:else}<EmptyState title="No completed matches in this selection" description="Choose another game or map to explore this player's history.">{#snippet actions()}<Button size="sm" onclick={() => void updateScope({ game: '', map: '' })}>Show all completed matches</Button>{/snippet}</EmptyState>{/if}
|
||||
</section>
|
||||
@@ -142,7 +146,7 @@
|
||||
<style>
|
||||
.profile { display: flex; flex-direction: column; gap: var(--space-6); min-width: 0; }
|
||||
.identity { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); color: var(--text-tertiary); font-size: var(--text-xs); }
|
||||
h2 { font-size: var(--text-lg); margin: 0 0 var(--space-3); }
|
||||
h2 { font-size: var(--text-lg); margin: 0 0 var(--space-3); scroll-margin-top: 6rem; }
|
||||
a { color: var(--accent-primary-hover); }
|
||||
.stats { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--space-3); }
|
||||
.stat { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-5); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); background: var(--surface); }
|
||||
@@ -160,6 +164,7 @@
|
||||
.scope-rank { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: 0 var(--space-5) var(--space-5); font-size: var(--text-sm); }
|
||||
.scope-rank p { margin: 0; }
|
||||
section > .note { margin-top: var(--space-3); }
|
||||
.mobile-records { display: none; }
|
||||
.table-scroll { max-width: 100%; overflow-x: auto; }
|
||||
table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
|
||||
th, td { padding: var(--space-4); border-bottom: 1px solid var(--border-subtle); text-align: right; white-space: nowrap; }
|
||||
@@ -172,5 +177,5 @@
|
||||
.pagination { padding: var(--space-4); justify-content: space-between; flex-wrap: wrap; font-size: var(--text-xs); color: var(--text-secondary); }
|
||||
summary { cursor: pointer; color: var(--text-secondary); }
|
||||
@media (max-width: 1000px) { .stats { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
|
||||
@media (max-width: 640px) { .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } .stat { padding: var(--space-3); } .stat strong { font-size: var(--text-xl); } .scope-controls { grid-template-columns: minmax(0, 1fr); } .scope-rank { align-items: flex-start; flex-direction: column; } }
|
||||
@media (max-width: 640px) { .mobile-records { display: block; } .desktop-records { display: none; } .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } .stat { padding: var(--space-3); } .stat strong { font-size: var(--text-xl); } .scope-controls { grid-template-columns: minmax(0, 1fr); } .scope-rank { align-items: flex-start; flex-direction: column; } }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user