@@ -15,6 +15,12 @@ const HorizontalRatingsChart = ({ questionId, questionTitle, filters = {}, showR
1515 const chartContainerRef = useRef ( null ) ;
1616 const [ containerWidth , setContainerWidth ] = useState ( 800 ) ;
1717
18+ // Helper function to truncate long labels
19+ const truncateLabel = ( label , maxLength = 35 ) => {
20+ if ( ! label || label . length <= maxLength ) return label ;
21+ return label . substring ( 0 , maxLength - 3 ) + '...' ;
22+ } ;
23+
1824 // Memoize filters to prevent infinite re-renders from object reference changes
1925 const filterKey = useMemo ( ( ) => JSON . stringify ( filters ) , [ filters ] ) ;
2026
@@ -384,7 +390,7 @@ const HorizontalRatingsChart = ({ questionId, questionTitle, filters = {}, showR
384390 }
385391
386392 return (
387- < div className = "relative" >
393+ < div className = "relative overflow-x-hidden " >
388394 < div
389395 className = "w-full bg-white border border-gray-300 rounded-[5px] flex overflow-hidden transition-all duration-200 shadow-sm"
390396 data-chart-id = { questionId }
@@ -440,7 +446,7 @@ const HorizontalRatingsChart = ({ questionId, questionTitle, filters = {}, showR
440446
441447 { /* Staircase/Waterfall Bars */ }
442448 < div className = "p-4" >
443- < div ref = { chartContainerRef } className = "relative w-full" style = { { height : `${ data . length * 24 + 10 } px` } } >
449+ < div ref = { chartContainerRef } className = "relative w-full overflow-x-hidden " style = { { height : `${ data . length * 24 + 10 } px` } } >
444450 { data . map ( ( item , index ) => {
445451 // Calculate cumulative percentage for positioning
446452 const cumulativePercentage = data
@@ -510,46 +516,48 @@ const HorizontalRatingsChart = ({ questionId, questionTitle, filters = {}, showR
510516 { /* Label positioning - always show descriptors next to bars */ }
511517 { isSmallBar ? (
512518 // For small bars, show label and percentage on the side of the bar
513- < div
514- className = "absolute flex items-center gap-1"
519+ < div
520+ className = "absolute flex items-center gap-1 max-w-full overflow-hidden "
515521 style = { {
516522 // Check if there's enough space on the left (need at least 20% for text)
517523 // Also check if this bar itself is wide enough to avoid overlap
518524 left : ( cumulativePercentage > 20 && barWidth < 15 ) ? `${ cumulativePercentage - 1 } %` : `${ cumulativePercentage + barWidth + 1 } %` ,
519525 top : '0px' ,
520526 height : '24px' ,
521- transform : ( cumulativePercentage > 20 && barWidth < 15 ) ? 'translateX(-100%)' : 'none'
527+ transform : ( cumulativePercentage > 20 && barWidth < 15 ) ? 'translateX(-100%)' : 'none' ,
528+ maxWidth : ( cumulativePercentage > 20 && barWidth < 15 ) ? `${ cumulativePercentage - 2 } %` : `${ 100 - cumulativePercentage - barWidth - 2 } %`
522529 } }
523530 >
524531 { /* Show percentage closest to bar, then descriptor */ }
525532 { ! percentageFitsInside && (
526- < span className = "text-gray-900 text-xs font-bold whitespace-nowrap" >
533+ < span className = "text-gray-900 text-xs font-bold whitespace-nowrap flex-shrink-0 " >
527534 { item . count === 0 ? '-' : ( Math . round ( item . percentage ) === 0 ? '<1%' : `${ Math . round ( item . percentage ) } %` ) }
528535 </ span >
529536 ) }
530- < span className = "text-gray-700 text-xs font-semibold uppercase whitespace-nowrap " >
537+ < span className = "text-gray-700 text-xs font-semibold uppercase truncate " >
531538 { item . label }
532539 </ span >
533540 </ div >
534541 ) : (
535542 // For normal bars, show descriptor next to the bar (left side if space, otherwise right)
536- < div
537- className = "absolute flex items-center gap-1"
543+ < div
544+ className = "absolute flex items-center gap-1 max-w-full overflow-hidden "
538545 style = { {
539546 // For larger bars, prefer left side if there's enough space (20%)
540547 left : cumulativePercentage > 20 ? `${ cumulativePercentage - 1 } %` : `${ cumulativePercentage + barWidth + 1 } %` ,
541548 top : '0px' ,
542549 height : '24px' ,
543- transform : cumulativePercentage > 20 ? 'translateX(-100%)' : 'none'
550+ transform : cumulativePercentage > 20 ? 'translateX(-100%)' : 'none' ,
551+ maxWidth : cumulativePercentage > 20 ? `${ cumulativePercentage - 2 } %` : `${ 100 - cumulativePercentage - barWidth - 2 } %`
544552 } }
545553 >
546554 { /* Show percentage closest to bar if it doesn't fit inside, then descriptor */ }
547555 { ! percentageFitsInside && (
548- < span className = "text-gray-900 text-xs font-bold whitespace-nowrap" >
556+ < span className = "text-gray-900 text-xs font-bold whitespace-nowrap flex-shrink-0 " >
549557 { item . count === 0 ? '-' : ( Math . round ( item . percentage ) === 0 ? '<1%' : `${ Math . round ( item . percentage ) } %` ) }
550558 </ span >
551559 ) }
552- < span className = "text-gray-700 text-xs font-semibold uppercase whitespace-nowrap " >
560+ < span className = "text-gray-700 text-xs font-semibold uppercase truncate " >
553561 { item . label }
554562 </ span >
555563 </ div >
0 commit comments