From 70505bd1fc91a83ec4ab15b92f5099a4e8752d77 Mon Sep 17 00:00:00 2001 From: hata <1553126902@qq.com> Date: Sun, 5 Jul 2026 06:48:24 +0800 Subject: [PATCH] fix(webui): finish mobile containment for inline code, tables, chips, user bubbles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 57f9ec0 added a CSS containment safety net for .markdown-content, but several rendering paths still overflowed or truncated on narrow viewports because they bypass those rules or actively disable wrapping: - Inline code longer than 120 chars renders as `block whitespace-pre` with no scroll container, so it bled past the viewport (white-space:pre defeats overflow-wrap). It now scrolls inside its own box via max-w-full overflow-x-auto. - Wide markdown tables never actually scrolled: Tailwind Typography forces width:100% + table-layout:auto on .prose table, so they shrank to fit instead of overflowing. Switched to a wrapper-
pattern (a custom `table` component, the approach used by DeepSeek/others) with min-w-max so wide tables keep natural column widths and scroll inside the conversation column; the old display:block rule on .markdown-content table is removed. - File-reference chips and inline link-preview cards used `truncate`, so long filenames/labels were ellipsized to one line. Now [overflow-wrap:anywhere] sm:truncate — wrap on mobile, truncate on desktop. - User-authored message bubbles don't pass through .markdown-content, so a long URL in the user's own message still burst the screen: under flex min-width:auto, break-words cannot reduce the item's min-content width. Added max-w-full min-w-0 + [overflow-wrap:anywhere]. No JS/agent/provider behavior touched. Desktop layout is unchanged — the new rules only engage when content would otherwise overflow. Verified: bun run lint (clean), bun run test (438 passed), bun run build. Refs #4693 Co-Authored-By: Claude --- webui/src/components/FileReferenceChip.tsx | 2 +- webui/src/components/MarkdownTextRenderer.tsx | 17 +++++++++++++++-- webui/src/components/MessageBubble.tsx | 4 ++-- webui/src/globals.css | 10 ++++------ 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/webui/src/components/FileReferenceChip.tsx b/webui/src/components/FileReferenceChip.tsx index 5526fec7..6298c42a 100644 --- a/webui/src/components/FileReferenceChip.tsx +++ b/webui/src/components/FileReferenceChip.tsx @@ -87,7 +87,7 @@ export function FileReferenceChip({ )} - + {label} @@ -417,7 +417,7 @@ export default function MarkdownTextRenderer({ return ( ); }, + table({ children, ...props }) { + // Wrap wide markdown tables in a horizontal-scroll container (the + // pattern used by DeepSeek/others) so a 6+ column table scrolls inside + // the conversation column instead of forcing the page wider than 100vw. + // min-w-max keeps natural column widths; w-full stretches narrow tables. + return ( +
+ + {children} +
+
+ ); + }, li({ children: markdownChildren, className: itemClassName }) { const link = inlineLinkPreviewFromChildren(markdownChildren); if (link) { diff --git a/webui/src/components/MessageBubble.tsx b/webui/src/components/MessageBubble.tsx index 7cb9cf97..51e8fb0b 100644 --- a/webui/src/components/MessageBubble.tsx +++ b/webui/src/components/MessageBubble.tsx @@ -147,8 +147,8 @@ export function MessageBubble({ {hasText ? (

by the markdown renderer's + custom `table` component (see MarkdownTextRenderer); min-w-max on the + keeps natural column widths so it scrolls instead of shrinking. */ /* Clip any residual horizontal bleed at the thread column edge. Vertical scrolling and internal code-block scroll are unaffected. */