@@ -510,29 +510,55 @@ export default class extends Controller {
510510 get _d3YScale ( ) {
511511 const dataMin = d3 . min ( this . _normalDataPoints , this . _getDatumValue ) ;
512512 const dataMax = d3 . max ( this . _normalDataPoints , this . _getDatumValue ) ;
513-
514- // Use 0 as baseline, but allow negative values if they exist
515- const yMin = Math . min ( 0 , dataMin ) ;
516-
517- // Handle edge case where all values are the same (including all zeros)
518- const range = dataMax - yMin ;
519- if ( range === 0 ) {
520- // If all values are 0, show 0-100 scale. Otherwise center the value with padding.
513+
514+ // Handle edge case where all values are the same
515+ if ( dataMin === dataMax ) {
521516 const padding = dataMax === 0 ? 100 : Math . abs ( dataMax ) * 0.5 ;
522517 return d3
523518 . scaleLinear ( )
524519 . rangeRound ( [ this . _d3ContainerHeight , 0 ] )
525- . domain ( [ yMin - padding , dataMax + padding ] ) ;
520+ . domain ( [ dataMin - padding , dataMax + padding ] ) ;
521+ }
522+
523+ const dataRange = dataMax - dataMin ;
524+ const avgValue = ( dataMax + dataMin ) / 2 ;
525+
526+ // Calculate relative change as a percentage
527+ const relativeChange = avgValue !== 0 ? dataRange / Math . abs ( avgValue ) : 1 ;
528+
529+ // Dynamic baseline calculation
530+ let yMin ;
531+ let yMax ;
532+
533+ // For small relative changes (< 10%), use a tighter scale
534+ if ( relativeChange < 0.1 && dataMin > 0 ) {
535+ // Start axis at a percentage below the minimum, not at 0
536+ const baselinePadding = dataRange * 2 ; // Show 2x the data range below min
537+ yMin = Math . max ( 0 , dataMin - baselinePadding ) ;
538+ yMax = dataMax + dataRange * 0.5 ; // Add 50% padding above
539+ } else {
540+ // For larger changes or when data crosses zero, use more context
541+ // Always include 0 when data is negative or close to 0
542+ if ( dataMin < 0 || ( dataMin >= 0 && dataMin < avgValue * 0.1 ) ) {
543+ yMin = Math . min ( 0 , dataMin * 1.1 ) ;
544+ } else {
545+ // Otherwise use dynamic baseline
546+ yMin = dataMin - dataRange * 0.3 ;
547+ }
548+ yMax = dataMax + dataRange * 0.1 ;
549+ }
550+
551+ // Adjust padding for labels if needed
552+ if ( this . useLabelsValue ) {
553+ const extraPadding = ( yMax - yMin ) * 0.1 ;
554+ yMin -= extraPadding ;
555+ yMax += extraPadding ;
526556 }
527-
528- // Add padding to prevent overlapping with labels and for visual breathing room
529- const topPadding = range * 0.1 ;
530- const bottomPadding = range * ( this . useLabelsValue ? 0.15 : 0.05 ) ;
531557
532558 return d3
533559 . scaleLinear ( )
534560 . rangeRound ( [ this . _d3ContainerHeight , 0 ] )
535- . domain ( [ yMin - bottomPadding , dataMax + topPadding ] ) ;
561+ . domain ( [ yMin , yMax ] ) ;
536562 }
537563
538564 _setupResizeObserver ( ) {
0 commit comments