authorclover caruso <git@paperclover.net> 2026-10-16 12:17:18-07:00
committerclover caruso <git@paperclover.net> 2026-10-16 16:52:04-07:00
log97b13b7697f982a8dfb6ebe7fd7b540861e75dd9
treecce1bc0992c6ed56cc633435a6f9580ec4bc8510
parent0b3f74c4692000e2979902e327e147f623276230
signature Signed by SSH key SHA256:cOKiuRFOeSRxne6EWgHtdQQSlBxjOXm2hOCFnCdLQbQ (~clover)

fix: wrap image batches across the message width

Clover wants large image batches to use the chat bubble width instead of stacking two narrow thumbnails per row. Expand batches above two media items into a responsive wrapping grid while retaining existing image controls, order, and small-batch sizing. Assisted-by: gpt-6.1-sol

1 files changed, 15 insertions(+), 2 deletions(-)

apps/web/src/components/chat/MessagesTimeline.tsx+15-2
...@@ -2324,6 +2324,7 @@ function UserTimelineRow({ row }: { row: Extract<TimelineRow, { kind: "message"...@@ -2324,6 +2324,7 @@ function UserTimelineRow({ row }: { row: Extract<TimelineRow, { kind: "message"
2324 }),2324 }),
2325 );2325 );
2326 const regularImages = userImages.filter((image) => !image.name.startsWith("preview-annotation-"));2326 const regularImages = userImages.filter((image) => !image.name.startsWith("preview-annotation-"));
2327 const hasMediaGrid = regularImages.length + userVideos.length > 2;
2327 const unchippedFiles = otherUserFiles.filter((file) => !chippedAttachmentIds.has(file.id));2328 const unchippedFiles = otherUserFiles.filter((file) => !chippedAttachmentIds.has(file.id));
2328 const annotationRecordIds = useMemo(2329 const annotationRecordIds = useMemo(
2329 () =>2330 () =>
...@@ -2487,10 +2488,22 @@ function UserTimelineRow({ row }: { row: Extract<TimelineRow, { kind: "message"...@@ -2487,10 +2488,22 @@ function UserTimelineRow({ row }: { row: Extract<TimelineRow, { kind: "message"
2487 {row.message.inputIntent && row.message.inputIntent !== "turn_start" ? (2488 {row.message.inputIntent && row.message.inputIntent !== "turn_start" ? (
2488 <UserMessageIntentMarker intent={row.message.inputIntent} />2489 <UserMessageIntentMarker intent={row.message.inputIntent} />
2489 ) : null}2490 ) : null}
2490 <div className="relative max-w-[80%] rounded-2xl bg-message p-3 text-message-foreground">2491 <div
2492 className={cn(
2493 "relative max-w-[80%] rounded-2xl bg-message p-3 text-message-foreground",
2494 hasMediaGrid && "w-[80%]",
2495 )}
2496 >
2491 <MessageAuthorHeading>You</MessageAuthorHeading>2497 <MessageAuthorHeading>You</MessageAuthorHeading>
2492 {(regularImages.length > 0 || userVideos.length > 0) && (2498 {(regularImages.length > 0 || userVideos.length > 0) && (
2493 <div className="mb-2 grid max-w-[210px] grid-cols-2 gap-2">2499 <div
2500 className={cn(
2501 "mb-2 grid gap-2",
2502 hasMediaGrid
2503 ? "grid-cols-[repeat(auto-fit,minmax(min(100%,100px),1fr))]"
2504 : "max-w-[210px] grid-cols-2",
2505 )}
2506 >
2494 {regularImages.map((image) => (2507 {regularImages.map((image) => (
2495 <div2508 <div
2496 key={image.id}2509 key={image.id}