Keep prompt text inside the Chat bubble

The prompt bubble is `w-fit max-w-[85%]`, so its width is measured
intrinsically and only then clamped. `items-start` left the inner content
wrapper intrinsically sized too, so it resolved against the available space
from before the clamp — the full column width — and kept that measurement
after the bubble shrank. The text laid out at 100% of the column while the
background painted at 85%, spilling out the right side.

Give the wrapper `w-full` so it fills the bubble's resolved width instead of
measuring itself. Short prompts still hug their content: a percentage-width
child contributes its content size during intrinsic sizing, so the bubble
measures the same and only the final wrap width changes. The expand button
keeps hugging its label as a separate flex child.

Also break long words in the collapsed preview. That is a separate overflow
path: the preview is raw prompt text under `whitespace-pre-wrap`, where an
unbreakable path or URL would spill even at the correct width.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-07-25 08:48:33 -04:00
parent 6b9bf2be80
commit d6a66844ff
No known key found for this signature in database

View file

@ -1481,11 +1481,18 @@ function ChatUserCard({ content }: { content: string }) {
const isLong = content.length > CHAT_PROMPT_PREVIEW_CHARS;
return (
<div className="flex w-fit max-w-[85%] flex-col items-start gap-1.5 self-end rounded-2xl rounded-br-md bg-panel px-4 py-3">
<div id={contentId}>
{/*
`w-full` is load-bearing. `items-start` keeps the expand button hugging
its label, but it also leaves this wrapper intrinsically sized, and the
bubble's own `w-fit` width is only clamped to `max-w-[85%]` after that
intrinsic pass. The text then keeps the wider pre-clamp measurement and
spills past the bubble. Filling the resolved width sidesteps it.
*/}
<div id={contentId} className="w-full">
{expanded ? (
<Markdown content={content} />
) : (
<p className="text-sm whitespace-pre-wrap text-fg-2">
<p className="text-sm break-words whitespace-pre-wrap text-fg-2">
{isLong
? `${content.slice(0, CHAT_PROMPT_PREVIEW_CHARS).trimEnd()}…`
: content}