feat(FN-5322): fix main chat composer flex sizing and expand behavior

Fixes the main chat composer flex sizing so the input area properly expands (FN-5322), with regression guards in the autosize test suite and a new browser layout smoke script covering the composer expand behavior.

Fusion-Task-Id: FN-5322
This commit is contained in:
Fusion (runfusion.ai)
2026-05-20 07:18:52 -07:00
committed by gsxdsm
parent cee2c1385a
commit 232a9fea86
4 changed files with 94 additions and 1 deletions

View File

@@ -0,0 +1,8 @@
---
"@runfusion/fusion": patch
---
Fix main chat composer (direct chat and rooms) so it visually grows on
multi-paragraph paste up to the 640px cap, matching QuickChat behavior.
The 640px cap from FN-5146 was already in place but an ancestor layout
constraint was clipping the rendered height.

View File

@@ -1395,7 +1395,11 @@
}
.chat-input-textarea {
flex: 1;
/* FN-5322: this textarea sits directly inside `.chat-input-wrapper`, which
is a column flex container (via AgentMentionPopup.css). Keep it out of
vertical flex sizing so the inline autosize height from ChatView.tsx is
honored instead of collapsing back toward the one-line minimum. */
flex: 0 0 auto;
resize: none;
border: 1px solid var(--border);
border-radius: 12px;

View File

@@ -11,6 +11,7 @@ describe("ChatView chat input autosize", () => {
expect(textareaRule).not.toBeNull();
expect(textareaRule?.[0]).toContain("max-height: 640px");
expect(textareaRule?.[0]).toContain("flex: 0 0 auto");
});
it("clamps oversized textarea growth to the new max height", () => {

View File

@@ -864,6 +864,86 @@ async function runSmokeChecks(page, pageUrl) {
&& prChecksLayout.detailsLinkColor !== "rgb(255, 255, 255)",
JSON.stringify(prChecksLayout),
);
const chatComposerLayout = await evaluate(page, `(() => {
const sandbox = document.createElement('section');
sandbox.setAttribute('data-smoke', 'chat-composer-fixture');
sandbox.style.position = 'fixed';
sandbox.style.left = '16px';
sandbox.style.bottom = '16px';
sandbox.style.width = '620px';
sandbox.style.maxWidth = 'calc(100vw - 32px)';
sandbox.style.zIndex = '5';
sandbox.style.background = 'var(--surface)';
sandbox.style.border = '1px solid var(--border)';
sandbox.innerHTML = [
'<div class="chat-input-area">',
' <div class="chat-input-row" data-smoke="chat-direct-composer">',
' <button type="button" class="btn-icon chat-attach-btn" aria-label="Attach files">+</button>',
' <div class="chat-input-wrapper">',
' <textarea class="chat-input-textarea" data-smoke="chat-direct-textarea" rows="1"></textarea>',
' </div>',
' <button type="button" class="chat-input-send" aria-label="Send">→</button>',
' </div>',
' <div class="chat-input-row" data-smoke="chat-room-composer">',
' <div class="chat-input-wrapper">',
' <textarea class="chat-input-textarea" data-smoke="chat-room-textarea" rows="1"></textarea>',
' </div>',
' <button type="button" class="chat-input-send" aria-label="Send">→</button>',
' </div>',
'</div>',
].join('');
document.body.appendChild(sandbox);
const tallDraft = Array.from({ length: 18 }, (_, index) => 'line ' + (index + 1)).join('\\n');
for (const textarea of sandbox.querySelectorAll('.chat-input-textarea')) {
textarea.value = tallDraft;
textarea.style.height = '500px';
}
const readLayout = (prefix) => {
const textarea = sandbox.querySelector('[data-smoke="' + prefix + '-textarea"]');
const wrapper = textarea.parentElement;
const textareaStyle = getComputedStyle(textarea);
const wrapperStyle = getComputedStyle(wrapper);
return {
textareaHeight: Math.round(textarea.getBoundingClientRect().height),
wrapperHeight: Math.round(wrapper.getBoundingClientRect().height),
textareaClientHeight: textarea.clientHeight,
wrapperClientHeight: wrapper.clientHeight,
textareaStyleHeight: textarea.style.height,
textareaFlexGrow: textareaStyle.flexGrow,
textareaFlexShrink: textareaStyle.flexShrink,
textareaFlexBasis: textareaStyle.flexBasis,
wrapperDisplay: wrapperStyle.display,
wrapperFlexDirection: wrapperStyle.flexDirection,
};
};
const result = {
direct: readLayout('chat-direct'),
room: readLayout('chat-room'),
};
sandbox.remove();
return result;
})()`);
assertSmokeResult(
"chat composer autosize geometry",
[chatComposerLayout.direct, chatComposerLayout.room].every((layout) =>
layout.textareaStyleHeight === "500px"
&& layout.textareaHeight >= 500
&& layout.wrapperHeight >= 500
&& layout.textareaClientHeight >= 498
&& layout.wrapperClientHeight >= 498
&& layout.textareaFlexGrow === "0"
&& layout.textareaFlexShrink === "0"
&& layout.textareaFlexBasis === "auto"
&& layout.wrapperDisplay === "flex"
&& layout.wrapperFlexDirection === "column"
),
JSON.stringify(chatComposerLayout),
);
}
async function main() {