Skip to content

Commit b2130d3

Browse files
committed
feat: add dark mode support for charts
1 parent ac1a865 commit b2130d3

1 file changed

Lines changed: 104 additions & 27 deletions

File tree

script.js

Lines changed: 104 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,37 @@
1+
// Theme-aware color palette for Chart.js (HSLA strings)
2+
const colors = {
3+
light: {
4+
vendors: {
5+
openai: 'hsla(0, 0%, 3%, .8)', // near-black accent
6+
google: 'hsla(217, 89%, 61%, .8)', // Google blue
7+
anthropic: 'hsla(15, 52%, 58%, .8)' // Anthropic orange
8+
},
9+
grid: 'hsla(240, 5%, 89%, 1)', // zinc-200-ish
10+
axis: 'hsla(240, 5%, 26%, 1)', // zinc-700-ish
11+
border: 'hsla(240, 5%, 84%, 1)' // zinc-300-ish
12+
},
13+
dark: {
14+
vendors: {
15+
openai: 'hsla(0, 0%, 80%, .8)', // brighter neutral for contrast
16+
google: 'hsla(217, 96%, 74%, .8)', // more saturated Google blue
17+
anthropic: 'hsla(15, 64%, 70%, .8)' // more saturated Anthropic orange
18+
},
19+
grid: 'hsla(240, 5%, 26%, 1)', // zinc-700-ish
20+
axis: 'hsla(240, 6%, 90%, 1)', // near-white text
21+
border: 'hsla(240, 5%, 36%, 1)' // zinc-600-ish
22+
}
23+
};
24+
25+
// Utilities
26+
function getCurrentTheme() {
27+
try {
28+
return (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ?
29+
'dark' : 'light';
30+
} catch (_) {
31+
return 'light';
32+
}
33+
}
34+
135
// Load details for a specific model
236
async function loadDetails(vendor, model, basePath = 'data/benchmarks/v0.8.1/default') {
337
try {
@@ -13,7 +47,7 @@ async function loadDetails(vendor, model, basePath = 'data/benchmarks/v0.8.1/def
1347
}
1448
}
1549

16-
// Create round distribution histogram
50+
// Create round distribution histogram (uses Chart.js defaults for fills)
1751
function createRoundHistogram(stats, canvasId) {
1852
const rounds = stats.map(stat => stat.final_round);
1953
const maxRound = Math.max(...rounds);
@@ -27,12 +61,15 @@ function createRoundHistogram(stats, canvasId) {
2761
const maxCount = Math.max(...counts);
2862

2963
const ctx = document.getElementById(canvasId).getContext('2d');
64+
const theme = getCurrentTheme();
65+
const themeColors = colors[theme] || colors.light;
66+
3067
new Chart(ctx, {
3168
type: 'bar',
3269
data: {
3370
labels: bins,
3471
datasets: [{
35-
data: counts,
72+
data: counts
3673
}]
3774
},
3875
options: {
@@ -54,19 +91,37 @@ function createRoundHistogram(stats, canvasId) {
5491
scales: {
5592
x: {
5693
title: {
57-
display: true,
94+
display: false,
5895
text: 'Round'
96+
},
97+
ticks: {
98+
color: themeColors.axis
99+
},
100+
grid: {
101+
color: themeColors.grid,
102+
borderColor: themeColors.border
103+
},
104+
border: {
105+
color: themeColors.border
59106
}
60107
},
61108
y: {
62109
beginAtZero: true,
63110
max: maxCount + 1,
64111
title: {
65-
display: true,
112+
display: false,
66113
text: 'Frequency'
67114
},
68115
ticks: {
69-
stepSize: 1
116+
stepSize: 1,
117+
color: themeColors.axis
118+
},
119+
grid: {
120+
color: themeColors.grid,
121+
borderColor: themeColors.border
122+
},
123+
border: {
124+
color: themeColors.border
70125
}
71126
}
72127
}
@@ -82,16 +137,11 @@ function createPerformanceBarChart(entries) {
82137
const models = [];
83138
const avgRounds = [];
84139
const stdDevs = [];
85-
const colors = [];
86-
const transparentColors = [];
140+
const strokeColors = [];
141+
const fillColors = [];
87142
const vendors = [];
88-
89-
// Color mapping for vendors
90-
const vendorColors = {
91-
'openai': '#374151', // Dark grey
92-
'anthropic': '#EA580C', // Dark orange
93-
'google': '#4285f4' // Google blue
94-
};
143+
const currentTheme = getCurrentTheme();
144+
const themePalette = colors[currentTheme] || colors.light;
95145

96146
entries.forEach(entry => {
97147
const modelParts = entry.config.model.split('/');
@@ -103,10 +153,9 @@ function createPerformanceBarChart(entries) {
103153
stdDevs.push(entry.std_dev_final_round);
104154
vendors.push(vendor);
105155

106-
const color = vendorColors[vendor] || '#6B7280';
107-
colors.push(color);
108-
// Add transparency to bars (70% opacity)
109-
transparentColors.push(color + 'B3'); // B3 = 70% opacity in hex
156+
const base = themePalette.vendors[vendor];
157+
strokeColors.push(base);
158+
fillColors.push(base);
110159
});
111160

112161
// Calculate Y-axis max to include error bars
@@ -120,8 +169,8 @@ function createPerformanceBarChart(entries) {
120169
datasets: [{
121170
label: 'Average Final Round',
122171
data: avgRounds,
123-
backgroundColor: transparentColors,
124-
borderColor: colors,
172+
backgroundColor: fillColors,
173+
borderColor: strokeColors,
125174
borderWidth: 0,
126175
errorBars: {
127176
'Average Final Round': {
@@ -155,6 +204,16 @@ function createPerformanceBarChart(entries) {
155204
title: {
156205
display: false,
157206
text: 'Model'
207+
},
208+
ticks: {
209+
color: themePalette.axis
210+
},
211+
grid: {
212+
color: themePalette.grid,
213+
borderColor: themePalette.border
214+
},
215+
border: {
216+
color: themePalette.border
158217
}
159218
},
160219
y: {
@@ -163,6 +222,16 @@ function createPerformanceBarChart(entries) {
163222
title: {
164223
display: false,
165224
text: 'Average Final Round'
225+
},
226+
ticks: {
227+
color: themePalette.axis
228+
},
229+
grid: {
230+
color: themePalette.grid,
231+
borderColor: themePalette.border
232+
},
233+
border: {
234+
color: themePalette.border
166235
}
167236
}
168237
},
@@ -192,8 +261,8 @@ function createPerformanceBarChart(entries) {
192261
// Draw error bar with vendor-specific color
193262
ctx.save();
194263
const vendor = vendors[index];
195-
ctx.strokeStyle = vendorColors[vendor] || '#6B7280';
196-
ctx.globalAlpha = 0.5; // make error bars slightly transparent
264+
const base = themePalette.vendors[vendor];
265+
ctx.strokeStyle = base;
197266
ctx.lineWidth = 4;
198267

199268
// Draw vertical line with square caps
@@ -226,18 +295,21 @@ function createPerformanceBarChart(entries) {
226295
}
227296

228297
// Create provider distribution pie chart
298+
// Provider distribution pie chart (uses defaults for fills; borders match background)
229299
function createProviderPieChart(data, canvasId) {
230300
const providers = Object.keys(data.providers || {});
231301
const counts = Object.values(data.providers || {});
232302

233303
const ctx = document.getElementById(canvasId).getContext('2d');
304+
const theme = getCurrentTheme();
305+
const themeColors = colors[theme] || colors.light;
234306
new Chart(ctx, {
235307
type: 'doughnut',
236308
data: {
237309
labels: providers,
238310
datasets: [{
239311
data: counts,
240-
borderWidth: 2,
312+
borderWidth: 1
241313
}]
242314
},
243315
options: {
@@ -249,6 +321,7 @@ function createProviderPieChart(data, canvasId) {
249321
position: 'bottom',
250322
labels: {
251323
boxWidth: 10,
324+
color: themeColors.axis,
252325
font: {
253326
size: 11
254327
}
@@ -259,7 +332,7 @@ function createProviderPieChart(data, canvasId) {
259332
text: 'Providers',
260333
}
261334
}
262-
}
335+
},
263336
});
264337
}
265338

@@ -572,7 +645,8 @@ async function loadLeaderboard(basePath = 'data/benchmarks/v0.8.1/default', disp
572645

573646
data.entries.forEach((entry, index) => {
574647
const row = document.createElement('tr');
575-
row.className = 'hover:bg-zinc-50 hover:dark:bg-zinc-700 transition-colors duration-150 lg:cursor-pointer';
648+
row.className =
649+
'hover:bg-zinc-50 hover:dark:bg-zinc-700 transition-colors duration-150 lg:cursor-pointer';
576650

577651
// Parse data based on display mode
578652
let primaryValue, secondaryValue, vendor, model;
@@ -608,8 +682,11 @@ async function loadLeaderboard(basePath = 'data/benchmarks/v0.8.1/default', disp
608682

609683
// Load and show details
610684
const data = await loadDetails(vendor, model, basePath);
611-
const detailRow = createDetailRow(data.stats, displayMode === 'community' ?
612-
primaryValue : model, data);
685+
const detailRow = createDetailRow(
686+
data.stats,
687+
displayMode === 'community' ? primaryValue : model,
688+
data
689+
);
613690
row.insertAdjacentElement('afterend', detailRow);
614691
}
615692
}

0 commit comments

Comments
 (0)