@@ -123,8 +123,10 @@ function createChart(data, containerId, type) {
123
123
}
124
124
125
125
const ctx = document . getElementById ( containerId ) . getContext ( '2d' ) ;
126
+
126
127
const options = {
127
128
responsive : true ,
129
+ maintainAspectRatio : false ,
128
130
plugins : {
129
131
title : {
130
132
display : true ,
@@ -157,6 +159,13 @@ function createChart(data, containerId, type) {
157
159
}
158
160
}
159
161
} ,
162
+ legend : {
163
+ position : 'top' ,
164
+ labels : {
165
+ boxWidth : 12 ,
166
+ padding : 10 ,
167
+ }
168
+ } ,
160
169
annotation : type === 'time' ? {
161
170
annotations : { }
162
171
} : undefined
@@ -227,6 +236,32 @@ function createChart(data, containerId, type) {
227
236
const chart = new Chart ( ctx , chartConfig ) ;
228
237
chartInstances . set ( containerId , chart ) ;
229
238
239
+ // Set explicit canvas size after chart creation to ensure proper sizing
240
+ const canvas = document . getElementById ( containerId ) ;
241
+ const rect = canvas . getBoundingClientRect ( ) ;
242
+ const dpr = window . devicePixelRatio || 1 ;
243
+
244
+ // Calculate dynamic height based on number of legend items
245
+ const legendItemCount = type === 'time' ?
246
+ Object . values ( data . runs ) . length :
247
+ data . datasets . length ;
248
+
249
+ // Base chart height + legend height (25px per line + padding)
250
+ const baseChartHeight = 350 ;
251
+ const legendHeight = Math . max ( legendItemCount * 25 , 50 ) ; // minimum 50px for legend
252
+ const totalHeight = baseChartHeight + legendHeight ;
253
+
254
+ // Set canvas dimensions for crisp rendering
255
+ canvas . width = rect . width * dpr ;
256
+ canvas . height = totalHeight * dpr ;
257
+
258
+ // Scale the context to ensure correct drawing operations
259
+ const context = canvas . getContext ( '2d' ) ;
260
+ context . scale ( dpr , dpr ) ;
261
+
262
+ // Force chart to use these exact dimensions
263
+ chart . resize ( rect . width , totalHeight ) ;
264
+
230
265
// Add annotation interaction handlers for time-series charts
231
266
if ( type === 'time' ) {
232
267
ChartAnnotations . setupAnnotationListeners ( chart , ctx , options ) ;
@@ -306,6 +341,10 @@ function createChartContainer(data, canvasId, type) {
306
341
container . setAttribute ( 'data-label' , data . label ) ;
307
342
container . setAttribute ( 'data-suite' , data . suite ) ;
308
343
344
+ // Create header section for metadata
345
+ const headerSection = document . createElement ( 'div' ) ;
346
+ headerSection . className = 'chart-header' ;
347
+
309
348
// Check if this benchmark is marked as unstable
310
349
const metadata = metadataForLabel ( data . label , type ) ;
311
350
if ( metadata && metadata . unstable ) {
@@ -316,15 +355,17 @@ function createChartContainer(data, canvasId, type) {
316
355
unstableWarning . className = 'benchmark-unstable' ;
317
356
unstableWarning . textContent = metadata . unstable ;
318
357
unstableWarning . style . display = isUnstableEnabled ( ) ? 'block' : 'none' ;
319
- container . appendChild ( unstableWarning ) ;
358
+ unstableWarning . style . marginBottom = '5px' ;
359
+ headerSection . appendChild ( unstableWarning ) ;
320
360
}
321
361
322
- // Add description if present in metadata (moved outside of details)
362
+ // Add description if present in metadata
323
363
if ( metadata && metadata . description ) {
324
364
const descElement = document . createElement ( 'div' ) ;
325
365
descElement . className = 'benchmark-description' ;
326
366
descElement . textContent = metadata . description ;
327
- container . appendChild ( descElement ) ;
367
+ descElement . style . marginBottom = '5px' ;
368
+ headerSection . appendChild ( descElement ) ;
328
369
}
329
370
330
371
// Add notes if present
@@ -333,7 +374,7 @@ function createChartContainer(data, canvasId, type) {
333
374
noteElement . className = 'benchmark-note' ;
334
375
noteElement . textContent = metadata . notes ;
335
376
noteElement . style . display = isNotesEnabled ( ) ? 'block' : 'none' ;
336
- container . appendChild ( noteElement ) ;
377
+ headerSection . appendChild ( noteElement ) ;
337
378
}
338
379
339
380
// Add tags if present
@@ -358,12 +399,31 @@ function createChartContainer(data, canvasId, type) {
358
399
tagsContainer . appendChild ( tagElement ) ;
359
400
} ) ;
360
401
361
- container . appendChild ( tagsContainer ) ;
402
+ headerSection . appendChild ( tagsContainer ) ;
362
403
}
363
404
405
+ // Add header section to container
406
+ container . appendChild ( headerSection ) ;
407
+
408
+ // Create main content section (chart + legend area)
409
+ const contentSection = document . createElement ( 'div' ) ;
410
+ contentSection . className = 'chart-content' ;
411
+
412
+ // Canvas for the chart - fixed position in content flow
364
413
const canvas = document . createElement ( 'canvas' ) ;
365
414
canvas . id = canvasId ;
366
- container . appendChild ( canvas ) ;
415
+ canvas . style . width = '100%' ;
416
+
417
+ // Set a default height - will be properly sized later in createChart
418
+ canvas . style . height = '400px' ;
419
+ canvas . style . marginBottom = '10px' ;
420
+ contentSection . appendChild ( canvas ) ;
421
+
422
+ container . appendChild ( contentSection ) ;
423
+
424
+ // Create footer section for details
425
+ const footerSection = document . createElement ( 'div' ) ;
426
+ footerSection . className = 'chart-footer' ;
367
427
368
428
// Create details section for extra info
369
429
const details = document . createElement ( 'details' ) ;
@@ -387,7 +447,8 @@ function createChartContainer(data, canvasId, type) {
387
447
extraInfo . innerHTML = generateExtraInfo ( data , 'benchmark' ) ;
388
448
details . appendChild ( extraInfo ) ;
389
449
390
- container . appendChild ( details ) ;
450
+ footerSection . appendChild ( details ) ;
451
+ container . appendChild ( footerSection ) ;
391
452
392
453
return container ;
393
454
}
0 commit comments