diff --git a/desktop/src/components/chat/UserMessage.test.tsx b/desktop/src/components/chat/UserMessage.test.tsx
new file mode 100644
index 00000000..efb519e9
--- /dev/null
+++ b/desktop/src/components/chat/UserMessage.test.tsx
@@ -0,0 +1,21 @@
+import { render, screen } from '@testing-library/react'
+import { describe, expect, it } from 'vitest'
+import { UserMessage } from './UserMessage'
+
+describe('UserMessage', () => {
+ it('keeps long URLs inside the message bubble', () => {
+ const longUrl = `https://cn.bing.com/search?q=${'encoded'.repeat(60)}`
+
+ const { container } = render()
+
+ const shell = container.querySelector('[data-message-shell="user"]')
+ const bubble = screen.getByText(longUrl)
+
+ expect(shell?.className).toContain('min-w-0')
+ expect(bubble.className).toContain('min-w-0')
+ expect(bubble.className).toContain('max-w-full')
+ expect(bubble.className).toContain('whitespace-pre-wrap')
+ expect(bubble.style.overflowWrap).toBe('anywhere')
+ expect(bubble.style.wordBreak).toBe('break-word')
+ })
+})
diff --git a/desktop/src/components/chat/UserMessage.tsx b/desktop/src/components/chat/UserMessage.tsx
index 9162384e..d66dadea 100644
--- a/desktop/src/components/chat/UserMessage.tsx
+++ b/desktop/src/components/chat/UserMessage.tsx
@@ -22,8 +22,12 @@ export function UserMessage({ content, attachments }: Props) {
{hasText && (
{content}
diff --git a/desktop/src/components/markdown/MarkdownRenderer.tsx b/desktop/src/components/markdown/MarkdownRenderer.tsx
index d9d0f236..f710de05 100644
--- a/desktop/src/components/markdown/MarkdownRenderer.tsx
+++ b/desktop/src/components/markdown/MarkdownRenderer.tsx
@@ -105,13 +105,13 @@ function parseMarkdown(content: string): { html: string; codeBlocks: CodeBlock[]
return { html, codeBlocks }
}
-const BASE_PROSE_CLASSES = `markdown-prose prose prose-sm max-w-none text-[var(--color-text-primary)]
+const BASE_PROSE_CLASSES = `markdown-prose prose prose-sm min-w-0 max-w-none break-words [overflow-wrap:anywhere] text-[var(--color-text-primary)]
prose-headings:text-[var(--color-text-primary)] prose-headings:font-semibold
prose-p:my-2 prose-p:leading-relaxed
- prose-p:break-words
+ prose-p:break-words prose-p:[overflow-wrap:anywhere]
prose-code:text-[13px] prose-code:text-[var(--color-code-fg)] prose-code:font-[var(--font-mono)] prose-code:bg-[var(--color-code-bg)] prose-code:border prose-code:border-[var(--color-border)] prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded-md prose-code:before:hidden prose-code:after:hidden
prose-pre:!bg-transparent prose-pre:!p-0 prose-pre:!shadow-none
- prose-a:text-[var(--color-text-accent)] prose-a:no-underline hover:prose-a:underline
+ prose-a:text-[var(--color-text-accent)] prose-a:no-underline prose-a:[overflow-wrap:anywhere] hover:prose-a:underline
prose-strong:text-[var(--color-text-primary)]
prose-ul:my-2 prose-ol:my-2
prose-li:my-0.5