fix(queued-messages): clamp long queued messages to 3 lines#3163
fix(queued-messages): clamp long queued messages to 3 lines#3163harshjainnn wants to merge 1 commit into
Conversation
Long queued messages (e.g. a pasted code block) previously rendered at full height, and this compounded with multiple queued messages, pushing the composer off-screen. Clamp to 3 lines with a fade mask and a 'Show more/less' toggle, mirroring the clamp pattern already used for sent messages in ChatThread's UserBubble. Fixes PostHog#3150
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
|
/trunk merge |
|
An error occurred while submitting your PR to the queue: |
|
Reviews (1): Last reviewed commit: "fix(queued-messages): clamp long queued ..." | Re-trigger Greptile |
| const [isExpanded, setIsExpanded] = useState(false); | ||
| const [isOverflowing, setIsOverflowing] = useState(false); | ||
| const textRef = useRef<HTMLDivElement>(null); | ||
|
|
||
| // Only meaningful while collapsed: expanding removes the clamp so scrollHeight === clientHeight. | ||
| // We keep the prior result when expanded so the "Show less" trigger stays put. | ||
| // biome-ignore lint/correctness/useExhaustiveDependencies: re-measure when the message text changes. | ||
| useLayoutEffect(() => { | ||
| if (isExpanded) return; | ||
| const el = textRef.current; | ||
| if (!el) return; | ||
| const measure = () => | ||
| setIsOverflowing(el.scrollHeight - el.clientHeight > 1); | ||
| measure(); | ||
| const observer = new ResizeObserver(measure); | ||
| observer.observe(el); | ||
| return () => observer.disconnect(); | ||
| }, [message.content, isExpanded]); |
There was a problem hiding this comment.
Duplicated expand/clamp logic — consider extracting a hook
The isExpanded/isOverflowing/ResizeObserver pattern introduced here is near-identical to the one already present in ChatThread.tsx's UserBubble (lines 298–315), and a simpler variant exists in UserMessage.tsx too. This is now the third copy. Extracting a useOverflowClamp(contentRef, dep) hook would satisfy the OnceAndOnlyOnce rule, make the threshold (3lh vs 5lh) a parameter, and give one place to fix the missing aria-expanded on the toggle button that all three share.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| <button | ||
| type="button" | ||
| onClick={() => setIsExpanded((v) => !v)} | ||
| className="mt-1 flex items-center gap-0.5 text-muted-foreground text-xs hover:text-foreground" | ||
| > |
There was a problem hiding this comment.
The toggle button is missing
aria-expanded, which is the standard accessibility attribute for disclosure widgets. Without it, screen readers can't announce the current collapsed/expanded state to users. The same omission exists in the original ChatThread.tsx UserBubble, but since this PR introduces the toggle in a new location it's worth fixing here.
| <button | |
| type="button" | |
| onClick={() => setIsExpanded((v) => !v)} | |
| className="mt-1 flex items-center gap-0.5 text-muted-foreground text-xs hover:text-foreground" | |
| > | |
| <button | |
| type="button" | |
| aria-expanded={isExpanded} | |
| onClick={() => setIsExpanded((v) => !v)} | |
| className="mt-1 flex items-center gap-0.5 text-muted-foreground text-xs hover:text-foreground" | |
| > |
Long queued messages (e.g. a pasted code block) previously rendered at full height, and this compounded with multiple queued messages, pushing the composer off-screen. Clamp to 3 lines with a fade mask and a 'Show more/less' toggle, mirroring the clamp pattern already used for sent messages in ChatThread's UserBubble.
Fixes #3150
Problem
Queued follow-up messages render at full height with no clamp. A long queued message (e.g. a pasted code block) can grow the dock to hundreds of pixels tall, and this compounds when multiple long messages are queued at once — pushing the composer off-screen.
Changes
Clamped
QueuedMessageViewcontent to 3 lines by default, with a bottom fade mask and a "Show more/less" toggle that only appears when the content actually overflows the clamp. This mirrors the existing clamp-by-measured-height pattern used inChatThread.tsx'sUserBubblefor sent messages — aResizeObservercomparesscrollHeightagainst the clampedclientHeight, since overflow can't be determined from character count alone (it depends on wrap width).Also changed the outer row's alignment from
align="center"toalign="start"so the icon and action buttons (Steer/Edit/Discard) stay pinned to the top when content spans multiple lines, instead of being vertically centered against a tall block.How did you test this?
Automatic notifications