fix: align chat messages and composer without horizontal overflow
Move message avatars into outer gutters and align message content with the composer while preserving existing colors and styling. Keep scrollbar space in the outer gutter to prevent horizontal scrolling. Release note: Chat avatars now sit outside message content, with the composer aligned to message edges and no extra horizontal scrollbar.
This commit is contained in:
@@ -116,11 +116,11 @@ describe('ChatTimeline', () => {
|
||||
expect(rule).not.toContain('contain-intrinsic')
|
||||
})
|
||||
|
||||
it('places message identity above the message body', () => {
|
||||
it.each(['assistant', 'user'] as const)('places the %s avatar outside the header and body', (role) => {
|
||||
const messages: Message[] = [
|
||||
{
|
||||
id: 'assistant-message',
|
||||
role: 'assistant',
|
||||
role,
|
||||
content: 'Answer',
|
||||
createdAt: 1_775_000_000_000,
|
||||
state: 'complete'
|
||||
@@ -145,9 +145,11 @@ describe('ChatTimeline', () => {
|
||||
const header = message?.querySelector('.message__header')
|
||||
const body = message?.querySelector('.message__body')
|
||||
|
||||
expect(header).toContainElement(message?.querySelector('.message__avatar') ?? null)
|
||||
const avatar = message?.querySelector('.message__avatar')
|
||||
|
||||
expect(avatar).toHaveAttribute('aria-hidden', 'true')
|
||||
expect(header).toContainElement(message?.querySelector('.message__meta') ?? null)
|
||||
expect(Array.from(message?.children ?? [])).toEqual([header, body])
|
||||
expect(Array.from(message?.children ?? [])).toEqual([avatar, header, body])
|
||||
})
|
||||
|
||||
it('enables HTML rendering only for completed Agent output', () => {
|
||||
|
||||
@@ -553,14 +553,14 @@ function ChatMessageRowView({
|
||||
ref={(element) => onArticleRef(message.id, element)}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div aria-hidden="true" className="message__avatar">
|
||||
{message.role === 'assistant' ? (
|
||||
<Bot size={18} />
|
||||
) : (
|
||||
<UserRound size={18} />
|
||||
)}
|
||||
</div>
|
||||
<div className="message__header">
|
||||
<div className="message__avatar">
|
||||
{message.role === 'assistant' ? (
|
||||
<Bot size={18} />
|
||||
) : (
|
||||
<UserRound size={18} />
|
||||
)}
|
||||
</div>
|
||||
<div className="message__meta">
|
||||
<strong>
|
||||
{message.role === 'assistant' ? 'GoodBuddy' : t('chat.user')}
|
||||
|
||||
@@ -248,7 +248,7 @@ describe('WorkspacePrimitives', () => {
|
||||
/@media \(max-width: 719px\)\s*\{(?:[^{}]|\{[^{}]*\})*?\.assistant-sidebar/u
|
||||
)
|
||||
expect(stylesheet).toMatch(
|
||||
/\.composer-wrap\s*\{[^}]*width:\s*100%;[^}]*max-width:\s*100%;[^}]*min-width:\s*0;[^}]*padding:\s*var\(--space-3\)\s*max\(var\(--page-gutter\),\s*calc\(\(100% - var\(--content-reading\)\) \/ 2\)\)\s*var\(--space-2\);/u
|
||||
/\.composer-wrap\s*\{[^}]*width:\s*100%;[^}]*max-width:\s*100%;[^}]*min-width:\s*0;[^}]*padding:\s*var\(--space-3\)\s*var\(--chat-inline-padding\)\s*var\(--space-2\);/u
|
||||
)
|
||||
expect(stylesheet).toMatch(
|
||||
/\.assistant-sidebar__tabs\s*\{[^}]*grid-template-columns:\s*repeat\(5,\s*minmax\(max-content,\s*1fr\)\);/u
|
||||
|
||||
@@ -5190,12 +5190,21 @@ button > svg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chat,
|
||||
.composer-wrap {
|
||||
--message-avatar-size: 29px;
|
||||
--chat-inline-padding: max(
|
||||
calc(var(--space-4) + var(--message-avatar-size) + var(--space-2)),
|
||||
calc((100cqw - var(--content-reading)) / 2)
|
||||
);
|
||||
}
|
||||
|
||||
.chat {
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
padding:
|
||||
var(--page-gutter)
|
||||
max(var(--page-gutter), calc((100% - var(--content-reading)) / 2))
|
||||
0
|
||||
10px;
|
||||
overflow-y: auto;
|
||||
background: var(--surface-raised);
|
||||
@@ -5333,6 +5342,13 @@ button > svg {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.chat > .welcome,
|
||||
.message-list {
|
||||
/* Keep the scrollbar inside the outer gutter without adding trailing scroll padding. */
|
||||
width: calc(100cqw - 2 * var(--chat-inline-padding));
|
||||
margin-left: var(--chat-inline-padding);
|
||||
}
|
||||
|
||||
.message-list {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
@@ -5363,9 +5379,10 @@ button > svg {
|
||||
}
|
||||
|
||||
.message {
|
||||
position: relative;
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
padding: 17px 8px;
|
||||
padding: 17px 0;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
@@ -5373,6 +5390,7 @@ button > svg {
|
||||
.message__header {
|
||||
display: flex;
|
||||
min-width: 0;
|
||||
min-height: var(--message-avatar-size);
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
@@ -5434,10 +5452,13 @@ button > svg {
|
||||
}
|
||||
|
||||
.message__avatar {
|
||||
position: absolute;
|
||||
top: 17px;
|
||||
left: calc(-1 * (var(--message-avatar-size) + var(--space-2)));
|
||||
display: grid;
|
||||
flex: 0 0 auto;
|
||||
width: 29px;
|
||||
height: 29px;
|
||||
width: var(--message-avatar-size);
|
||||
height: var(--message-avatar-size);
|
||||
place-items: center;
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 9px;
|
||||
@@ -5446,6 +5467,8 @@ button > svg {
|
||||
}
|
||||
|
||||
.message--user .message__avatar {
|
||||
right: calc(-1 * (var(--message-avatar-size) + var(--space-2)));
|
||||
left: auto;
|
||||
border-color: var(--accent-selected);
|
||||
background: var(--accent-subtle);
|
||||
color: var(--accent);
|
||||
@@ -6511,7 +6534,7 @@ button > svg {
|
||||
min-width: 0;
|
||||
padding:
|
||||
var(--space-3)
|
||||
max(var(--page-gutter), calc((100% - var(--content-reading)) / 2))
|
||||
var(--chat-inline-padding)
|
||||
var(--space-2);
|
||||
background: var(--surface-raised);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user