fix(nexus): use flex layout for assistant chat thread container
Phase 9 used `h-[calc(100vh-320px)] min-h-[320px]` on the thread wrapper because `@tanstack/react-virtual` needs an explicit height for its virtual scroll root. The calc was brittle — any change to TopStrip or input bar sizing broke the math and let the thread overflow or collapse below 320px. Phase 16a replaces the calc with a pure flex chain: - PersonalAssistant forks its root column: when a conversation is active it renders a `flex-1 min-h-0` child that centers the message list at max-w-[760px] and delegates scroll to the list's own internal virtual scroller. When no conversation is active the old `overflow-auto` wrapper remains so the greeting and empty state still scroll. - ChatMessageList's root becomes `flex min-h-0 flex-1 flex-col`, and its inner scroll div becomes `flex-1 min-h-0 overflow-auto`. The virtualizer now measures the actual flex-derived height, which tracks input-bar size changes automatically. Tests: src/components/frame/ + src/components/assistant/ + ChatMessageList.test — 109 passed (6 todo). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
14dd8dbfa5
commit
4ff707bdcb
2 changed files with 33 additions and 25 deletions
|
|
@ -138,10 +138,10 @@ export function ChatMessageList({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative flex-1">
|
<div className="relative flex min-h-0 flex-1 flex-col">
|
||||||
<div
|
<div
|
||||||
ref={parentRef}
|
ref={parentRef}
|
||||||
className="h-full overflow-auto p-3"
|
className="flex-1 min-h-0 overflow-auto p-3"
|
||||||
onScroll={handleScroll}
|
onScroll={handleScroll}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -282,31 +282,39 @@ export function PersonalAssistant() {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Conversation thread — full-bleed, max-width 760px centered */}
|
{/* Conversation thread — full-bleed, max-width 760px centered.
|
||||||
<div className="flex-1 min-h-0 overflow-auto">
|
Phase 16a replaced the old `h-[calc(100vh-320px)]` wrapper with
|
||||||
<div className="mx-auto w-full max-w-[760px] px-6 py-8">
|
a pure flex-1 column so the virtualizer inherits its scroll
|
||||||
{showHomeGreeting && (
|
height from the flex layout instead of hard-coded viewport
|
||||||
<AssistantHomeGreeting
|
arithmetic. Greeting and empty-state variants still scroll via
|
||||||
status={homeStatus}
|
the outer `overflow-auto`; the active-conversation variant
|
||||||
userName={selectedCompany?.name ?? null}
|
delegates scroll to ChatMessageList's internal virtual scroller. */}
|
||||||
|
{hasActiveConversation && selectedConvId ? (
|
||||||
|
<div className="flex flex-1 min-h-0 justify-center">
|
||||||
|
<div className="flex w-full max-w-[760px] min-h-0 flex-1 flex-col">
|
||||||
|
<ChatMessageList
|
||||||
|
conversationId={selectedConvId}
|
||||||
|
streamingContent={streamingContent}
|
||||||
|
isStreaming={isStreaming}
|
||||||
/>
|
/>
|
||||||
)}
|
</div>
|
||||||
|
|
||||||
{hasActiveConversation && selectedConvId && (
|
|
||||||
<div className="h-[calc(100vh-320px)] min-h-[320px]">
|
|
||||||
<ChatMessageList
|
|
||||||
conversationId={selectedConvId}
|
|
||||||
streamingContent={streamingContent}
|
|
||||||
isStreaming={isStreaming}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!showHomeGreeting && !selectedConvId && conversationCount === 0 && (
|
|
||||||
<p className="text-sm text-muted-foreground">No conversations yet.</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
) : (
|
||||||
|
<div className="flex-1 min-h-0 overflow-auto">
|
||||||
|
<div className="mx-auto w-full max-w-[760px] px-6 py-8">
|
||||||
|
{showHomeGreeting && (
|
||||||
|
<AssistantHomeGreeting
|
||||||
|
status={homeStatus}
|
||||||
|
userName={selectedCompany?.name ?? null}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!showHomeGreeting && !selectedConvId && conversationCount === 0 && (
|
||||||
|
<p className="text-sm text-muted-foreground">No conversations yet.</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Phase 12 — promote-to-project overlay. Absolutely positioned so
|
{/* Phase 12 — promote-to-project overlay. Absolutely positioned so
|
||||||
the chat canvas is covered during the animation while keeping
|
the chat canvas is covered during the animation while keeping
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue