Skip to content

Commit c929ffb

Browse files
committed
feat: update truncatable text
1 parent a2ac1d9 commit c929ffb

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

front_end/src/app/(embed)/questions/components/truncatable_question_title.tsx

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ type TruncatableQuestionTitleProps = HTMLAttributes<HTMLHeadingElement> & {
1010
revealOnHoverOrTap?: boolean;
1111
};
1212

13+
const GRADIENT_EXTRA_PX = 12;
14+
1315
const 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

Comments
 (0)