From befb49b1e6f2789f57b590bb5ec008ca06acbe27 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Sun, 28 Jun 2026 14:56:52 -0700 Subject: [PATCH] FN-7204: make narrow chat messages full width Narrow chat surfaces now let messages span their constrained container width. - Add a ChatView container query that makes all message variants full-width in narrow hosts such as Quick Chat popups and the right dock. - Update the mobile bubble cap to full width while preserving tablet assistant widening and desktop caps. - Cover the responsive CSS contracts in dashboard tests and document the behavior with a patch changeset. Files changed: .changeset/fn-7204-full-width-chat-messages.md | 7 +++++++ docs/dashboard-guide.md | 6 +++--- packages/dashboard/app/components/ChatView.css | 12 +++++++++++- .../__tests__/ChatView.core-contracts.test.tsx | 20 +++++++++++++++++--- .../components/__tests__/ChatView.mobile.test.tsx | 4 ++-- 5 files changed, 40 insertions(+), 9 deletions(-) Fusion-Task-Id: FN-7204 Fusion-Task-Lineage: 19da0d46-f0bf-46e7-9f87-900c5184f378 Co-authored-by: Fusion (runfusion.ai) --- .../fn-7204-full-width-chat-messages.md | 7 +++++++ docs/dashboard-guide.md | 6 +++--- .../dashboard/app/components/ChatView.css | 12 ++++++++++- .../ChatView.core-contracts.test.tsx | 20 ++++++++++++++++--- .../__tests__/ChatView.mobile.test.tsx | 4 ++-- 5 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 .changeset/fn-7204-full-width-chat-messages.md diff --git a/.changeset/fn-7204-full-width-chat-messages.md b/.changeset/fn-7204-full-width-chat-messages.md new file mode 100644 index 0000000000..6fe0d81273 --- /dev/null +++ b/.changeset/fn-7204-full-width-chat-messages.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Chat messages now use the full width in narrow popup and sidebar chats. +category: fix +dev: ChatView.css adds a `@container chat-view (max-width: 30rem)` rule setting `.chat-message` to max-width:100%, plus the mobile viewport rule bumped from 90% to 100%. diff --git a/docs/dashboard-guide.md b/docs/dashboard-guide.md index 1639bb0b7a..0a1dcbf324 100644 --- a/docs/dashboard-guide.md +++ b/docs/dashboard-guide.md @@ -361,8 +361,8 @@ Chat view provides project-scoped conversations with agents. - Direct chat sessions can be renamed from the desktop conversation context menu and from the mobile session switcher; blank rename submissions clear the custom title so the default session label is shown again. - On desktop/tablet Direct chat, the thread header shows an estimated token count against the active model's known context window (for example `~12.3k / 200k`). It is hidden on mobile, narrow floating chat, rooms, and unknown-context-window models. - -- On mobile (`max-width: 768px`), chat bubbles are slightly wider in full Chat for improved readability while preserving header/composer gutters. On tablet-width main Chat containers, assistant/agent, streaming, and failure bubbles use a wider reading measure for long responses while user bubbles and narrow floating Quick Chat hosts stay bounded. + +- In narrow Chat containers (including phone-width full Chat, narrow Quick Chat popups, and right-dock Chat), message bubbles use the full content width for improved readability. On tablet-width main Chat containers, assistant/agent, streaming, and failure bubbles keep the wider 88% reading measure, while wide desktop Chat keeps the standard 75% bubble cap. - Full Chat tool-call summaries now use a denser mobile layout: grouped and single-call collapsed rows keep icon + label + status on one line (Quick Chat-style scanability) while expanded details remain unchanged. - Assistant question tool calls now render as a shared in-chat response card instead of a generic tool-call disclosure. The card recognizes provider-native question tools and Fusion's `fn_ask_question`, supports select, multi-select, text, and yes/no prompts, sends the formatted answer back into the same direct or room thread, and renders historical answered questions read-only. @@ -427,7 +427,7 @@ Quick Chat is an optional fast, project-scoped assistant surface for conversatio - FAB dragging uses pointer events with document-level move/up tracking and a 5px drag threshold so Android touch drags reposition reliably while short taps still open Quick Chat - Quick Chat now mirrors full Chat tail behavior: if you scroll up, live updates stop auto-following and a **Latest** jump control appears until you jump back down. - On mobile, Quick Chat re-anchors to the newest message whenever the panel is opened/reopened and when page visibility is restored, while still preserving the near-bottom gate so intentional scroll-away keeps **Latest** jump behavior. -- On mobile, Quick Chat bubbles are slightly wider while keeping compact tool-call summary layout and full-screen/safe-area behavior intact. +- On mobile and other narrow Quick Chat container widths, Quick Chat bubbles use the full content width while keeping compact tool-call summary layout and full-screen/safe-area behavior intact. - On mobile, the fullscreen Quick Chat sheet follows soft-keyboard `visualViewport` height/offset samples directly, dedupes repeated identical samples, and smooths Android resize-content height-only changes so the sheet does not visibly step while the keyboard animates. iOS-style non-zero `offsetTop` samples still apply synchronously so transform alignment stays exact. - On mobile, Quick Chat send reliability includes a delivery watchdog: if a queued message would otherwise stay stranded in the composer after a dropped or suspended stream, it is re-confirmed and delivered once no generation is in flight and no live stream is connected, so sends are not silently dropped. - On mobile, Quick Chat sends exactly once per tap even when the browser emits paired pointer and touch events; a stop tap immediately after send is still honored. diff --git a/packages/dashboard/app/components/ChatView.css b/packages/dashboard/app/components/ChatView.css index d849a0f8f2..d7b82372de 100644 --- a/packages/dashboard/app/components/ChatView.css +++ b/packages/dashboard/app/components/ChatView.css @@ -1034,6 +1034,16 @@ Tablet Chat View has enough message-pane width for assistant prose, markdown, to } } +/* +FNXC:ChatView 2026-06-28-14:47: +Narrow chat hosts need full-width bubbles for prose, code, tool output, failures, streams, and attachments in already-constrained columns. Key this to the ChatView container width, not the viewport, so Quick Chat popups and the right dock on desktop viewports match phone-width Chat View behavior. +*/ +@container chat-view (max-width: 30rem) { + .chat-message { + max-width: 100%; + } +} + .chat-message-avatar { display: flex; align-items: center; @@ -2239,7 +2249,7 @@ Queued-message banners stack above the composer input with a capped scroll area, } .chat-message { - max-width: 90%; + max-width: 100%; } .chat-message-failure-details summary, diff --git a/packages/dashboard/app/components/__tests__/ChatView.core-contracts.test.tsx b/packages/dashboard/app/components/__tests__/ChatView.core-contracts.test.tsx index 68ad5133b6..7c52b3e8e2 100644 --- a/packages/dashboard/app/components/__tests__/ChatView.core-contracts.test.tsx +++ b/packages/dashboard/app/components/__tests__/ChatView.core-contracts.test.tsx @@ -424,10 +424,10 @@ describe("ChatView CSS — failure bubble contracts", () => { }); }); -describe("ChatView CSS — tablet assistant bubble width", () => { +describe("ChatView CSS — responsive bubble width", () => { const css = loadAllAppCss(); - it("widens assistant, streaming, and failure bubbles on tablet containers while preserving user and mobile caps", async () => { + it("widens assistant, streaming, and failure bubbles on tablet containers while preserving desktop and mobile rules", async () => { const baseMessageRule = css.match(/\.chat-message\s*\{([^}]*)\}/); const userRule = css.match(/\.chat-message--user\s*\{([^}]*)\}/); const tabletRule = css.match( @@ -441,7 +441,21 @@ describe("ChatView CSS — tablet assistant bubble width", () => { /\.chat-message--assistant,\s*\.chat-message--streaming,\s*\.chat-message--failure\s*\{[^}]*max-width:\s*88%/, ); expect(tabletRule?.[1]).not.toMatch(/\.chat-message--user\s*\{[^}]*max-width/); - expect(css).toMatch(/@media\s*\(max-width:\s*768px\)[\s\S]*?\.chat-message\s*\{[^}]*max-width:\s*90%/); + expect(css).toMatch(/@media\s*\(max-width:\s*768px\)[\s\S]*?\.chat-message\s*\{[^}]*max-width:\s*100%/); + }); + + it("makes all chat message variants full-width in narrow chat-view containers without changing desktop or tablet caps", async () => { + const baseMessageRule = css.match(/\.chat-message\s*\{([^}]*)\}/); + const narrowRule = css.match(/@container\s+chat-view\s+\(max-width:\s*30rem\)\s*\{([\s\S]*?)\n\}/); + const tabletRule = css.match( + /@container\s+chat-view\s+\(min-width:\s*48\.0625rem\)\s+and\s+\(max-width:\s*64rem\)\s*\{([\s\S]*?)\n\}/, + ); + + expect(baseMessageRule?.[1]).toContain("max-width: 75%"); + expect(narrowRule?.[1]).toMatch(/\.chat-message\s*\{[^}]*max-width:\s*100%/); + expect(tabletRule?.[1]).toMatch( + /\.chat-message--assistant,\s*\.chat-message--streaming,\s*\.chat-message--failure\s*\{[^}]*max-width:\s*88%/, + ); }); }); diff --git a/packages/dashboard/app/components/__tests__/ChatView.mobile.test.tsx b/packages/dashboard/app/components/__tests__/ChatView.mobile.test.tsx index f76088d051..d846516e09 100644 --- a/packages/dashboard/app/components/__tests__/ChatView.mobile.test.tsx +++ b/packages/dashboard/app/components/__tests__/ChatView.mobile.test.tsx @@ -1801,8 +1801,8 @@ describe("ChatView mobile CSS contract", () => { expect(css).toMatch(/@media\s*\(max-width:\s*768px\)[\s\S]*?\.chat-thread--keyboard-active\s*\{[^}]*--vv-height/); }); - it("mobile widens chat bubbles for readability", async () => { - expect(css).toMatch(/@media\s*\(max-width:\s*768px\)[\s\S]*?\.chat-message\s*\{[^}]*max-width:\s*90%/); + it("mobile makes chat bubbles full-width for narrow-column readability", async () => { + expect(css).toMatch(/@media\s*\(max-width:\s*768px\)[\s\S]*?\.chat-message\s*\{[^}]*max-width:\s*100%/); }); it("mobile keeps thread-header identity and render toggle inline", async () => {