@@ -90,6 +90,21 @@ function buildOption(spec: ChartSpec, rows: Array<Record<string, unknown>> | nul
9090 if ( spec . title && option . title === undefined ) {
9191 option . title = { text : spec . title }
9292 }
93+ // Gentle layout defaults — fill in ONLY what the spec leaves unset. A title
94+ // and a legend both default to the top edge and overlap; when both are
95+ // present and the legend declares no position, drop it below the title.
96+ const legend = option . legend
97+ if (
98+ option . title !== undefined &&
99+ legend !== null &&
100+ typeof legend === 'object' &&
101+ ! Array . isArray ( legend )
102+ ) {
103+ const positioned = legend as Record < string , unknown >
104+ if ( positioned . top === undefined && positioned . bottom === undefined ) {
105+ positioned . top = 32
106+ }
107+ }
93108 return option as EChartsOption
94109}
95110
@@ -210,10 +225,17 @@ export const ChartPreview = memo(function ChartPreview({
210225 }
211226
212227 const waitingOnRows = Boolean ( tableSource ) && ! rowsQuery . data
228+ // Width-driven aspect box, not full-bleed: a chart stretched to the whole
229+ // panel height is unreadable in a tall resource pane. ECharts follows the
230+ // box through the ResizeObserver above.
213231 return (
214- < div className = 'relative min-h-0 flex-1' >
215- { ( ! echartsLib || waitingOnRows ) && < PreviewLoadingFrame className = 'h-full flex-1' /> }
216- < div ref = { containerRef } className = 'size-full min-h-[320px]' />
232+ < div className = 'min-h-0 flex-1 overflow-auto p-6' >
233+ < div className = 'relative mx-auto w-full max-w-[1024px]' >
234+ { ( ! echartsLib || waitingOnRows ) && (
235+ < PreviewLoadingFrame className = 'absolute inset-0 z-10' />
236+ ) }
237+ < div ref = { containerRef } className = 'aspect-[16/10] min-h-[280px] w-full' />
238+ </ div >
217239 </ div >
218240 )
219241} )
0 commit comments