diff --git a/apps/desktop/src/app/chat/composer/index.tsx b/apps/desktop/src/app/chat/composer/index.tsx index f6a5c5ff48d..44ad0fa2a39 100644 --- a/apps/desktop/src/app/chat/composer/index.tsx +++ b/apps/desktop/src/app/chat/composer/index.tsx @@ -12,7 +12,6 @@ import { useRef, useState } from 'react' -import { createPortal } from 'react-dom' import { hermesDirectiveFormatter, type SlashChipKind } from '@/components/assistant-ui/directive-text' import { composerFill, composerSurfaceGlass } from '@/components/chat/composer-dock' @@ -1924,7 +1923,7 @@ export function ChatBar({ ) - const composerOverlay = ( + return ( <> {dragging && poppedOut && (
- - ) - - return ( - <> - {/* Floating: portal to so position:fixed resolves against the - viewport. The chat content wrapper sets `contain: layout paint`, which - makes it a containing block for (and clips) fixed descendants — left - inline, the popped-out composer is positioned/clipped relative to the - chat column (which shifts with the sidebars), not the viewport, so the - viewport-based clamp can't keep it on-screen. Docked stays inline: it's - `absolute` within that column by design. */} - {poppedOut ? createPortal(composerOverlay, document.body) : composerOverlay} -
- - {showChatBar && ( - }> - - + {resumeExhausted && routedSessionId && ( +
+ +
+ +
+
+
)} -
- {resumeExhausted && routedSessionId && ( -
- -
- -
-
-
+ {showChatBar && } + + +
+ {/* Composer renders OUTSIDE the contain:[layout paint] wrapper above: + that wrapper is a containing block for — and clips — position:fixed + descendants, so the popped-out (fixed) composer would anchor to the + chat column (which shifts/resizes with the sidebars) and get clipped + off-screen instead of floating against the viewport. As a sibling it + anchors to the outer relative container instead: docked is absolute + (identical placement), floating resolves against the viewport. Both + states stay mounted here, so dock⇄float never remounts the editor. */} + {showChatBar && ( + }> + + )} - {showChatBar && } - - -
+ ) }