From 675e01407d10417547024c86a6ed26e6fca30cf3 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Sat, 16 May 2026 08:54:22 -0700 Subject: [PATCH 1/2] =?UTF-8?q?fix(chat):=20user-bubble=20word-wrap=20?= =?UTF-8?q?=E2=80=94=20give=20.chat-message=5F=5Flayout=20width:100%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Short user messages like "Show me the dashboard" wrap mid-phrase ("Show me the" / "dashboard"). Fixed three times before in #313, #325, and c0b9e88c, each by tweaking which element holds the 80% cap — none addressed the architecture. Root cause: user-role host is `display:flex; justify-content:flex-end` with no width on .chat-message__layout. __main has max-width:80%, which resolves against layout (its containing block). Layout in turn shrinks to __main's content (flex item with auto basis). The browser breaks the circular dependency by capping the bubble at its fit-content intrinsic (~166px = the wrap-point width) instead of max-content (~200px = full text on one line). Verified live: forced max-content = 199.75px, fit-content = 166.20px, with old layoutW = 207.75px — the bug is exact. Fix: layout gets width:100% so __main's 80% has a concrete (and full- row) containing block. Host switches from flex to block; right-alignment moves down to layout (`justify-content: flex-end` on the layout flex container). Verified via chrome MCP after fix: bubbleW = 199.75px (full max-content), mainW = 199.75px, layoutW = 720px (full row), bubble renders single-line right-aligned. Co-Authored-By: Claude Opus 4.7 --- .../chat-message/chat-message.component.ts | 13 ++++++++++- .../src/lib/styles/chat-message.styles.ts | 23 +++++++++++-------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/libs/chat/src/lib/primitives/chat-message/chat-message.component.ts b/libs/chat/src/lib/primitives/chat-message/chat-message.component.ts index 3a547e5b7..89b17996a 100644 --- a/libs/chat/src/lib/primitives/chat-message/chat-message.component.ts +++ b/libs/chat/src/lib/primitives/chat-message/chat-message.component.ts @@ -16,7 +16,18 @@ export type ChatMessageRole = 'user' | 'assistant' | 'system' | 'tool'; imports: [ChatCitationsComponent, ChatCheckpointMarkerComponent], changeDetection: ChangeDetectionStrategy.OnPush, styles: [CHAT_HOST_TOKENS, CHAT_MESSAGE_STYLES, ` - .chat-message__layout { display: flex; gap: 8px; align-items: flex-start; } + /* + * Layout MUST be width:100% so user-role __main's max-width:80% (defined + * in chat-message.styles.ts) has a concrete containing block to resolve + * against. Without this, layout shrinks to __main's content, __main + * shrinks to its bubble's content, the bubble's fit-content is then + * capped by max-width:80% of layout (a circular dependency the browser + * breaks at the bubble's wrap-point intrinsic width — ~166px instead of + * the unwrapped ~199px), forcing short user phrases like "Show me the + * dashboard" to wrap mid-message. See PRs #313, #325, c0b9e88c — each + * shifted which element held the 80% cap but none gave it a stable base. + */ + .chat-message__layout { display: flex; gap: 8px; align-items: flex-start; width: 100%; } .chat-message__gutter { flex: 0 0 14px; display: flex; align-items: flex-start; padding-top: 4px; } .chat-message__gutter:empty { flex-basis: 0; } .chat-message__main { flex: 1; min-width: 0; } diff --git a/libs/chat/src/lib/styles/chat-message.styles.ts b/libs/chat/src/lib/styles/chat-message.styles.ts index 66916add1..b87acf0e5 100644 --- a/libs/chat/src/lib/styles/chat-message.styles.ts +++ b/libs/chat/src/lib/styles/chat-message.styles.ts @@ -3,19 +3,22 @@ export const CHAT_MESSAGE_STYLES = ` :host { display: block; } :host([data-role="user"]) { - display: flex; - justify-content: flex-end; + /* + * Block (not flex) so the layout child gets its width:100% (set in + * chat-message.component.ts inline styles). Right-alignment happens + * inside layout via justify-content:flex-end below, NOT here. The old + * `display:flex; justify-content:flex-end` on the host caused layout + * to shrink-wrap its content, which collapsed __main's 80% containing + * block — see chat-message.component.ts comment for the full story. + */ + display: block; margin-top: 0.5rem; } :host([data-role="user"][data-prev-role="assistant"]) { margin-top: 1.5rem; } - /* - * For user-role messages, the bubble's containing column must size to - * content rather than collapse via the flex chain. Without this, the - * bubble's max-width: 80% (defined below) resolves against a collapsed - * parent (~58px instead of the full row), capping the bubble below - * intrinsic single-word width and forcing mid-word wraps like - * "hello" → "hel" / "lo". See PR #313 follow-up. - */ + :host([data-role="user"]) .chat-message__layout { + /* Right-align the bubble column inside the full-width row. */ + justify-content: flex-end; + } :host([data-role="user"]) .chat-message__main { flex: none; width: fit-content; From 86f5b9eed83815d6eb2865d5b215c0630988d412 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Sat, 16 May 2026 09:11:59 -0700 Subject: [PATCH 2/2] fix(chat): escape backticks in chat-message style comment (CI break) --- libs/chat/src/lib/styles/chat-message.styles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/chat/src/lib/styles/chat-message.styles.ts b/libs/chat/src/lib/styles/chat-message.styles.ts index b87acf0e5..698c1bcae 100644 --- a/libs/chat/src/lib/styles/chat-message.styles.ts +++ b/libs/chat/src/lib/styles/chat-message.styles.ts @@ -7,7 +7,7 @@ export const CHAT_MESSAGE_STYLES = ` * Block (not flex) so the layout child gets its width:100% (set in * chat-message.component.ts inline styles). Right-alignment happens * inside layout via justify-content:flex-end below, NOT here. The old - * `display:flex; justify-content:flex-end` on the host caused layout + * "display:flex; justify-content:flex-end" on the host caused layout * to shrink-wrap its content, which collapsed __main's 80% containing * block — see chat-message.component.ts comment for the full story. */