forked from CSGOWTF/csgowtf
style: Redesign match detail pages with neon esports aesthetic
Complete overhaul of all 7 match sub-pages (Overview, Flashes, Economy, Details, Weapons, Damage, Chat) with consistent neon design system. Key changes: - Update Card/Tabs components with void backgrounds and neon accents - Add decorative blur orbs and grid pattern to match layout hero - Convert DaisyUI classes to custom Tailwind with neon colors - Update chart components with neon-themed tooltips and grid styling - Add RoundTimeline neon glow on selection with void-themed tooltips Puns added throughout: - "Hall of Shame" for players who flash teammates more than enemies - "Needs Therapy Award" for high team damage - "MVP (Most Violent Player)" badge - "The Poverty Round", "YOLO Buy" economy labels - "Multi-Threat Level", "Can't Touch This", "Molotov Mixologist" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -72,9 +72,9 @@
|
||||
|
||||
<Card padding="lg">
|
||||
<div class="mb-6">
|
||||
<h2 class="text-2xl font-bold text-base-content">Round Timeline</h2>
|
||||
<p class="mt-2 text-sm text-base-content/60">
|
||||
Click on a round to see detailed information. T = Terrorists, CT = Counter-Terrorists
|
||||
<h2 class="text-2xl font-bold text-white">Round Timeline</h2>
|
||||
<p class="mt-2 text-sm text-white/60">
|
||||
Click on a round to see the battle details. T = Terrorists, CT = Counter-Terrorists
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -100,25 +100,20 @@
|
||||
>
|
||||
<!-- Round number -->
|
||||
<div
|
||||
class="mb-2 text-xs font-semibold transition-colors"
|
||||
class:text-primary={isSelected}
|
||||
class:opacity-60={!isSelected}
|
||||
class="mb-2 text-xs font-semibold transition-colors {isSelected
|
||||
? 'text-neon-blue'
|
||||
: 'text-white/60'}"
|
||||
>
|
||||
{round.round}
|
||||
</div>
|
||||
|
||||
<!-- Round indicator circle -->
|
||||
<div
|
||||
class="relative flex h-12 w-12 items-center justify-center rounded-full border-2 transition-all"
|
||||
class:border-terrorist={isWinner2}
|
||||
class:bg-terrorist={isWinner2}
|
||||
class:bg-opacity-20={isWinner2 || isWinner3}
|
||||
class:border-ct={isWinner3}
|
||||
class:bg-ct={isWinner3}
|
||||
class:ring-4={isSelected}
|
||||
class:ring-primary={isSelected}
|
||||
class:ring-opacity-30={isSelected}
|
||||
class:scale-110={isSelected}
|
||||
class="relative flex h-12 w-12 items-center justify-center rounded-full border-2 transition-all {isWinner2
|
||||
? 'border-terrorist bg-terrorist/20'
|
||||
: ''} {isWinner3 ? 'border-ct bg-ct/20' : ''} {isSelected
|
||||
? 'scale-110 shadow-[0_0_15px_rgba(0,212,255,0.4)] ring-2 ring-neon-blue'
|
||||
: ''}"
|
||||
>
|
||||
<!-- Win reason icon or T/CT badge -->
|
||||
{#if Icon}
|
||||
@@ -147,18 +142,18 @@
|
||||
<!-- Connecting line to next round -->
|
||||
{#if round.round < rounds.length}
|
||||
<div
|
||||
class="absolute left-[60px] top-[34px] h-0.5 w-[calc(100%-60px)] bg-base-300"
|
||||
class="absolute left-[60px] top-[34px] h-0.5 w-[calc(100%-60px)] bg-white/10"
|
||||
></div>
|
||||
{/if}
|
||||
|
||||
<!-- Hover tooltip -->
|
||||
<div
|
||||
class="pointer-events-none absolute top-full z-10 mt-2 hidden w-48 rounded-lg bg-base-100 p-3 text-left shadow-xl ring-1 ring-base-300 group-hover:block"
|
||||
class="pointer-events-none absolute top-full z-10 mt-2 hidden w-48 rounded-lg border border-white/10 bg-void-light p-3 text-left shadow-xl backdrop-blur-sm group-hover:block"
|
||||
>
|
||||
<div class="text-xs font-semibold text-base-content">
|
||||
<div class="text-xs font-semibold text-white">
|
||||
Round {round.round}
|
||||
</div>
|
||||
<div class="mt-1 text-xs text-base-content/80">
|
||||
<div class="mt-1 text-xs text-white/80">
|
||||
Winner:
|
||||
<span
|
||||
class="font-bold"
|
||||
@@ -168,10 +163,10 @@
|
||||
{isWinner2 ? 'Terrorists' : 'Counter-Terrorists'}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-1 text-xs text-base-content/60">
|
||||
<div class="mt-1 text-xs text-white/60">
|
||||
{getWinReasonText(round.win_reason)}
|
||||
</div>
|
||||
<div class="mt-2 text-xs text-base-content/60">
|
||||
<div class="mt-2 text-xs text-white/60">
|
||||
Score: {scoreAtRound.teamA} - {scoreAtRound.teamB}
|
||||
</div>
|
||||
</div>
|
||||
@@ -196,13 +191,13 @@
|
||||
|
||||
<!-- Selected Round Details -->
|
||||
{#if selectedRoundData}
|
||||
<div class="mt-6 border-t border-base-300 pt-6">
|
||||
<div class="mt-6 border-t border-white/10 pt-6">
|
||||
<div class="mb-4 flex items-center justify-between">
|
||||
<h3 class="text-xl font-bold text-base-content">
|
||||
<h3 class="text-xl font-bold text-white">
|
||||
Round {selectedRoundData.round} Details
|
||||
</h3>
|
||||
<button
|
||||
class="btn btn-ghost btn-sm"
|
||||
class="rounded-lg px-3 py-1.5 text-sm text-white/60 transition-colors hover:bg-white/5 hover:text-white"
|
||||
onclick={() => (selectedRound = null)}
|
||||
aria-label="Close details"
|
||||
>
|
||||
@@ -212,7 +207,7 @@
|
||||
|
||||
<div class="grid gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<div class="text-sm text-base-content/60">Winner</div>
|
||||
<div class="text-sm text-white/50">Winner</div>
|
||||
<div
|
||||
class="text-lg font-bold"
|
||||
class:text-terrorist={selectedRoundData.winner === 2}
|
||||
@@ -222,8 +217,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm text-base-content/60">Win Reason</div>
|
||||
<div class="text-lg font-semibold text-base-content">
|
||||
<div class="text-sm text-white/50">Win Reason</div>
|
||||
<div class="text-lg font-semibold text-white">
|
||||
{getWinReasonText(selectedRoundData.win_reason)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -232,37 +227,46 @@
|
||||
<!-- Player stats for the round if available -->
|
||||
{#if selectedRoundData.players && selectedRoundData.players.length > 0}
|
||||
<div class="mt-4">
|
||||
<h4 class="mb-2 text-sm font-semibold text-base-content">Round Economy</h4>
|
||||
<h4 class="mb-2 text-sm font-semibold text-white">Round Economy</h4>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table table-sm">
|
||||
<table class="w-full text-sm">
|
||||
<thead>
|
||||
<tr class="border-base-300">
|
||||
<th>Player</th>
|
||||
<th>Bank</th>
|
||||
<th>Equipment</th>
|
||||
<th>Spent</th>
|
||||
<tr class="border-b border-white/10 text-left text-white/50">
|
||||
<th class="px-3 py-2">Player</th>
|
||||
<th class="px-3 py-2">Bank</th>
|
||||
<th class="px-3 py-2">Equipment</th>
|
||||
<th class="px-3 py-2">Spent</th>
|
||||
{#if selectedRoundData.players.some((p) => p.kills_in_round !== undefined)}
|
||||
<th>Kills</th>
|
||||
<th class="px-3 py-2">Kills</th>
|
||||
{/if}
|
||||
{#if selectedRoundData.players.some((p) => p.damage_in_round !== undefined)}
|
||||
<th>Damage</th>
|
||||
<th class="px-3 py-2">Damage</th>
|
||||
{/if}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each selectedRoundData.players as player}
|
||||
<tr class="border-base-300">
|
||||
<td class="font-medium"
|
||||
<tr class="border-b border-white/5 transition-colors hover:bg-white/5">
|
||||
<td class="px-3 py-2 font-medium text-white"
|
||||
>Player {player.player_id || player.match_player_id || '?'}</td
|
||||
>
|
||||
<td class="font-mono text-success">${player.bank.toLocaleString()}</td>
|
||||
<td class="font-mono">${player.equipment.toLocaleString()}</td>
|
||||
<td class="font-mono text-error">${player.spent.toLocaleString()}</td>
|
||||
<td class="px-3 py-2 font-mono text-neon-green"
|
||||
>${player.bank.toLocaleString()}</td
|
||||
>
|
||||
<td class="px-3 py-2 font-mono text-white/80"
|
||||
>${player.equipment.toLocaleString()}</td
|
||||
>
|
||||
<td class="px-3 py-2 font-mono text-neon-red"
|
||||
>${player.spent.toLocaleString()}</td
|
||||
>
|
||||
{#if selectedRoundData.players.some((p) => p.kills_in_round !== undefined)}
|
||||
<td class="font-mono">{player.kills_in_round || 0}</td>
|
||||
<td class="px-3 py-2 font-mono text-white/80">{player.kills_in_round || 0}</td
|
||||
>
|
||||
{/if}
|
||||
{#if selectedRoundData.players.some((p) => p.damage_in_round !== undefined)}
|
||||
<td class="font-mono">{player.damage_in_round || 0}</td>
|
||||
<td class="px-3 py-2 font-mono text-white/80"
|
||||
>{player.damage_in_round || 0}</td
|
||||
>
|
||||
{/if}
|
||||
</tr>
|
||||
{/each}
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
display: true,
|
||||
position: 'top',
|
||||
labels: {
|
||||
color: 'rgb(156, 163, 175)',
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
font: {
|
||||
family: 'Inter, system-ui, sans-serif',
|
||||
size: 12
|
||||
@@ -64,21 +64,21 @@
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||
backgroundColor: 'rgba(18, 18, 26, 0.95)',
|
||||
padding: 12,
|
||||
titleColor: '#fff',
|
||||
bodyColor: '#fff',
|
||||
borderColor: 'rgba(255, 255, 255, 0.1)',
|
||||
bodyColor: 'rgba(255, 255, 255, 0.8)',
|
||||
borderColor: 'rgba(0, 212, 255, 0.3)',
|
||||
borderWidth: 1
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
grid: {
|
||||
color: 'rgba(156, 163, 175, 0.1)'
|
||||
color: 'rgba(255, 255, 255, 0.05)'
|
||||
},
|
||||
ticks: {
|
||||
color: 'rgb(156, 163, 175)',
|
||||
color: 'rgba(255, 255, 255, 0.5)',
|
||||
font: {
|
||||
size: 11
|
||||
}
|
||||
@@ -86,10 +86,10 @@
|
||||
},
|
||||
y: {
|
||||
grid: {
|
||||
color: 'rgba(156, 163, 175, 0.1)'
|
||||
color: 'rgba(255, 255, 255, 0.05)'
|
||||
},
|
||||
ticks: {
|
||||
color: 'rgb(156, 163, 175)',
|
||||
color: 'rgba(255, 255, 255, 0.5)',
|
||||
font: {
|
||||
size: 11
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
display: true,
|
||||
position: 'top',
|
||||
labels: {
|
||||
color: 'rgb(156, 163, 175)',
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
font: {
|
||||
family: 'Inter, system-ui, sans-serif',
|
||||
size: 12
|
||||
@@ -73,21 +73,21 @@
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||
backgroundColor: 'rgba(18, 18, 26, 0.95)',
|
||||
padding: 12,
|
||||
titleColor: '#fff',
|
||||
bodyColor: '#fff',
|
||||
borderColor: 'rgba(255, 255, 255, 0.1)',
|
||||
bodyColor: 'rgba(255, 255, 255, 0.8)',
|
||||
borderColor: 'rgba(0, 212, 255, 0.3)',
|
||||
borderWidth: 1
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
grid: {
|
||||
color: 'rgba(156, 163, 175, 0.1)'
|
||||
color: 'rgba(255, 255, 255, 0.05)'
|
||||
},
|
||||
ticks: {
|
||||
color: 'rgb(156, 163, 175)',
|
||||
color: 'rgba(255, 255, 255, 0.5)',
|
||||
font: {
|
||||
size: 11
|
||||
}
|
||||
@@ -95,10 +95,10 @@
|
||||
},
|
||||
y: {
|
||||
grid: {
|
||||
color: 'rgba(156, 163, 175, 0.1)'
|
||||
color: 'rgba(255, 255, 255, 0.05)'
|
||||
},
|
||||
ticks: {
|
||||
color: 'rgb(156, 163, 175)',
|
||||
color: 'rgba(255, 255, 255, 0.5)',
|
||||
font: {
|
||||
size: 11
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
display: true,
|
||||
position: 'bottom',
|
||||
labels: {
|
||||
color: 'rgb(156, 163, 175)',
|
||||
color: 'rgba(255, 255, 255, 0.7)',
|
||||
font: {
|
||||
family: 'Inter, system-ui, sans-serif',
|
||||
size: 12
|
||||
@@ -63,11 +63,11 @@
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||
backgroundColor: 'rgba(18, 18, 26, 0.95)',
|
||||
padding: 12,
|
||||
titleColor: '#fff',
|
||||
bodyColor: '#fff',
|
||||
borderColor: 'rgba(255, 255, 255, 0.1)',
|
||||
bodyColor: 'rgba(255, 255, 255, 0.8)',
|
||||
borderColor: 'rgba(0, 212, 255, 0.3)',
|
||||
borderWidth: 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
children
|
||||
}: Props = $props();
|
||||
|
||||
const baseClasses = 'bg-base-200 border border-base-300 rounded-md transition-all duration-200';
|
||||
const baseClasses = 'bg-void-light border border-white/10 rounded-xl transition-all duration-300';
|
||||
|
||||
const variantClasses = {
|
||||
default: 'shadow-sm',
|
||||
elevated: 'shadow-lg shadow-black/10',
|
||||
default: 'shadow-sm hover:shadow-[0_0_20px_rgba(0,212,255,0.05)]',
|
||||
elevated: 'shadow-lg shadow-black/20 hover:shadow-[0_0_30px_rgba(0,212,255,0.1)]',
|
||||
interactive:
|
||||
'cursor-pointer hover:border-primary hover:shadow-lg hover:shadow-primary/20 hover:-translate-y-0.5'
|
||||
'cursor-pointer hover:border-neon-blue/50 hover:shadow-[0_0_20px_rgba(0,212,255,0.15)] hover:-translate-y-0.5'
|
||||
};
|
||||
|
||||
const paddingClasses = {
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
tabs: Tab[];
|
||||
activeTab?: string;
|
||||
onTabChange?: (value: string) => void;
|
||||
variant?: 'boxed' | 'bordered' | 'lifted';
|
||||
size?: 'xs' | 'sm' | 'md' | 'lg';
|
||||
size?: 'sm' | 'md' | 'lg';
|
||||
class?: string;
|
||||
}
|
||||
|
||||
@@ -21,7 +20,6 @@
|
||||
tabs,
|
||||
activeTab = $bindable(),
|
||||
onTabChange,
|
||||
variant = 'bordered',
|
||||
size = 'md',
|
||||
class: className = ''
|
||||
}: Props = $props();
|
||||
@@ -43,21 +41,36 @@
|
||||
}
|
||||
};
|
||||
|
||||
const variantClass =
|
||||
variant === 'boxed' ? 'tabs-boxed' : variant === 'lifted' ? 'tabs-lifted' : '';
|
||||
const sizeClass =
|
||||
size === 'xs' ? 'tabs-xs' : size === 'sm' ? 'tabs-sm' : size === 'lg' ? 'tabs-lg' : '';
|
||||
const sizeClasses = {
|
||||
sm: 'text-xs px-3 py-1.5',
|
||||
md: 'text-sm px-4 py-2',
|
||||
lg: 'text-base px-5 py-2.5'
|
||||
};
|
||||
|
||||
const baseTabClasses = 'rounded-md font-medium transition-all duration-200 whitespace-nowrap';
|
||||
|
||||
const inactiveClasses = 'text-white/60 hover:text-white hover:bg-white/5';
|
||||
|
||||
const activeClasses =
|
||||
'text-neon-blue bg-neon-blue/10 border border-neon-blue/50 shadow-[0_0_10px_rgba(0,212,255,0.15)]';
|
||||
|
||||
const disabledClasses = 'opacity-40 cursor-not-allowed pointer-events-none';
|
||||
</script>
|
||||
|
||||
<div role="tablist" class="tabs {variantClass} {sizeClass} {className}">
|
||||
<div
|
||||
role="tablist"
|
||||
class="inline-flex gap-1 rounded-lg bg-void/50 p-1 backdrop-blur-sm {className}"
|
||||
>
|
||||
{#each tabs as tab}
|
||||
{@const active = isActive(tab)}
|
||||
{@const classes = `${baseTabClasses} ${sizeClasses[size]} ${active ? activeClasses : inactiveClasses} ${tab.disabled ? disabledClasses : ''}`}
|
||||
|
||||
{#if tab.href}
|
||||
<a
|
||||
href={tab.href}
|
||||
role="tab"
|
||||
class="tab"
|
||||
class:tab-active={isActive(tab)}
|
||||
class:tab-disabled={tab.disabled}
|
||||
class={classes}
|
||||
aria-selected={active}
|
||||
aria-disabled={tab.disabled}
|
||||
>
|
||||
{tab.label}
|
||||
@@ -65,9 +78,8 @@
|
||||
{:else}
|
||||
<button
|
||||
role="tab"
|
||||
class="tab"
|
||||
class:tab-active={isActive(tab)}
|
||||
class:tab-disabled={tab.disabled}
|
||||
class={classes}
|
||||
aria-selected={active}
|
||||
disabled={tab.disabled}
|
||||
onclick={() => handleTabClick(tab)}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user