@@ -10,6 +10,8 @@ type TruncatableQuestionTitleProps = HTMLAttributes<HTMLHeadingElement> & {
1010 revealOnHoverOrTap ?: boolean ;
1111} ;
1212
13+ const GRADIENT_EXTRA_PX = 12 ;
14+
1315const TruncatableQuestionTitle : React . FC < TruncatableQuestionTitleProps > = ( {
1416 children,
1517 className,
@@ -25,6 +27,8 @@ const TruncatableQuestionTitle: React.FC<TruncatableQuestionTitleProps> = ({
2527} ) => {
2628 const [ expanded , setExpanded ] = useState ( false ) ;
2729 const [ isTruncated , setIsTruncated ] = useState ( false ) ;
30+ const [ contentHeight , setContentHeight ] = useState < number | null > ( null ) ;
31+ const [ clampedHeight , setClampedHeight ] = useState < number | null > ( null ) ;
2832 const titleRef = useRef < HTMLHeadingElement | null > ( null ) ;
2933
3034 const hasClamp = maxLines > 0 ;
@@ -42,20 +46,23 @@ const TruncatableQuestionTitle: React.FC<TruncatableQuestionTitleProps> = ({
4246 const el = titleRef . current ;
4347 if ( ! el || ! hasClamp ) {
4448 setIsTruncated ( false ) ;
49+ setContentHeight ( null ) ;
50+ setClampedHeight ( null ) ;
4551 return ;
4652 }
4753
4854 const checkTruncation = ( ) => {
49- const truncated = el . scrollHeight > el . clientHeight + 1 ;
50- setIsTruncated ( truncated ) ;
55+ const client = el . clientHeight ;
56+ const scroll = el . scrollHeight ;
57+
58+ setClampedHeight ( client ) ;
59+ setContentHeight ( scroll ) ;
60+ setIsTruncated ( scroll > client + 1 ) ;
5161 } ;
5262
5363 checkTruncation ( ) ;
5464
55- const observer = new ResizeObserver ( ( ) => {
56- checkTruncation ( ) ;
57- } ) ;
58-
65+ const observer = new ResizeObserver ( checkTruncation ) ;
5966 observer . observe ( el ) ;
6067 return ( ) => observer . disconnect ( ) ;
6168 } , [ children , maxLines , hasClamp ] ) ;
@@ -77,6 +84,10 @@ const TruncatableQuestionTitle: React.FC<TruncatableQuestionTitleProps> = ({
7784
7885 const showOverlay = revealOnHoverOrTap && isTruncated && expanded ;
7986
87+ const baseHeight = showOverlay ? contentHeight : clampedHeight ;
88+ const gradientHeight =
89+ baseHeight != null ? baseHeight + GRADIENT_EXTRA_PX : undefined ;
90+
8091 return (
8192 < div
8293 className = { cn ( "relative w-full" , revealOnHoverOrTap && "cursor-pointer" ) }
@@ -105,7 +116,11 @@ const TruncatableQuestionTitle: React.FC<TruncatableQuestionTitleProps> = ({
105116 { ...rest }
106117 ref = { titleRef }
107118 className = { className }
108- style = { { ...clampStyle , ...style } }
119+ style = { {
120+ ...clampStyle ,
121+ ...style ,
122+ ...( showOverlay ? { visibility : "hidden" } : { } ) ,
123+ } }
109124 >
110125 { children }
111126 </ QuestionTitle >
@@ -120,10 +135,11 @@ const TruncatableQuestionTitle: React.FC<TruncatableQuestionTitleProps> = ({
120135
121136 < div
122137 className = { cn (
123- "pointer-events-none absolute inset-x-0 top-full z-10 h -10" ,
138+ "pointer-events-none absolute inset-x-0 top-0 z -10" ,
124139 "bg-gradient-to-b from-blue-100/0 via-blue-100/90 to-blue-100" ,
125140 "dark:from-blue-100-dark/0 dark:via-blue-100-dark/90 dark:to-blue-100-dark"
126141 ) }
142+ style = { gradientHeight ? { height : gradientHeight } : undefined }
127143 />
128144 </ >
129145 ) }
0 commit comments