Files
csgowtf/src/lib/components/charts/BarChart.svelte
vikingowl ee233bb6fb 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>
2025-12-07 17:54:29 +01:00

131 lines
2.6 KiB
Svelte

<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import {
Chart,
BarController,
BarElement,
LinearScale,
CategoryScale,
Title,
Tooltip,
Legend,
type ChartConfiguration
} from 'chart.js';
// Register Chart.js components
Chart.register(BarController, BarElement, LinearScale, CategoryScale, Title, Tooltip, Legend);
interface Props {
data: {
labels: string[];
datasets: Array<{
label: string;
data: number[];
backgroundColor?: string | string[];
borderColor?: string | string[];
borderWidth?: number;
}>;
};
options?: Partial<ChartConfiguration<'bar'>['options']>;
height?: number;
horizontal?: boolean;
class?: string;
}
let {
data,
options = {},
height = 300,
horizontal = false,
class: className = ''
}: Props = $props();
let canvas: HTMLCanvasElement;
let chart: Chart<'bar'> | null = null;
// Convert Svelte 5 $state proxy to plain object for Chart.js compatibility
// Using JSON parse/stringify to handle Svelte proxies that structuredClone can't handle
const plainData = $derived(JSON.parse(JSON.stringify(data)));
const defaultOptions: ChartConfiguration<'bar'>['options'] = {
responsive: true,
maintainAspectRatio: false,
indexAxis: horizontal ? 'y' : 'x',
plugins: {
legend: {
display: true,
position: 'top',
labels: {
color: 'rgba(255, 255, 255, 0.7)',
font: {
family: 'Inter, system-ui, sans-serif',
size: 12
}
}
},
tooltip: {
backgroundColor: 'rgba(18, 18, 26, 0.95)',
padding: 12,
titleColor: '#fff',
bodyColor: 'rgba(255, 255, 255, 0.8)',
borderColor: 'rgba(0, 212, 255, 0.3)',
borderWidth: 1
}
},
scales: {
x: {
grid: {
color: 'rgba(255, 255, 255, 0.05)'
},
ticks: {
color: 'rgba(255, 255, 255, 0.5)',
font: {
size: 11
}
}
},
y: {
grid: {
color: 'rgba(255, 255, 255, 0.05)'
},
ticks: {
color: 'rgba(255, 255, 255, 0.5)',
font: {
size: 11
}
}
}
}
};
onMount(() => {
const ctx = canvas.getContext('2d');
if (ctx) {
chart = new Chart(ctx, {
type: 'bar',
data: plainData,
options: { ...defaultOptions, ...options }
});
}
});
onDestroy(() => {
if (chart) {
chart.destroy();
}
});
// Watch for data changes and update chart
$effect(() => {
if (chart && plainData) {
chart.data = plainData;
chart.options = { ...defaultOptions, ...options };
chart.update();
}
});
</script>
<div class="relative w-full {className}" style="height: {height}px">
<canvas bind:this={canvas}></canvas>
</div>