diff --git a/packages/dashboard/app/components/ChatView.css b/packages/dashboard/app/components/ChatView.css index f9d5aa7fe..e17d4b7cb 100644 --- a/packages/dashboard/app/components/ChatView.css +++ b/packages/dashboard/app/components/ChatView.css @@ -1103,7 +1103,7 @@ display: none; } - .chat-thread[style*="--keyboard-overlap"] { + .chat-thread--keyboard-active { height: calc(var(--vv-height, calc(100dvh - var(--keyboard-overlap, 0px))) - var(--header-height)); max-height: calc(var(--vv-height, calc(100dvh - var(--keyboard-overlap, 0px))) - var(--header-height)); /* useMobileKeyboard pins --vv-offset-top across pan-time scroll diff --git a/packages/dashboard/app/components/ChatView.tsx b/packages/dashboard/app/components/ChatView.tsx index 0ed0b7b0b..7198f24bf 100644 --- a/packages/dashboard/app/components/ChatView.tsx +++ b/packages/dashboard/app/components/ChatView.tsx @@ -795,8 +795,13 @@ export function ChatView({ projectId, addToast }: ChatViewProps) { enabled: isMobile && !!activeSession, }); + // Only opt into visual-viewport sizing when we have concrete keyboard + // displacement (overlap or offset). The shared hook can report `keyboardOpen` + // during iOS settle/shrink phases with zero overlap; forcing vv-height in that + // transient state shrinks the thread and pushes the composer upward. + const hasKeyboardViewportDisplacement = keyboardOverlap > 0 || viewportOffsetTop > 0; const threadKeyboardStyle: CSSProperties = - keyboardOpen + keyboardOpen && hasKeyboardViewportDisplacement ? ({ "--keyboard-overlap": `${keyboardOverlap}px`, "--vv-offset-top": `${viewportOffsetTop}px`, @@ -1711,7 +1716,10 @@ export function ChatView({ projectId, addToast }: ChatViewProps) { )} {/* Thread */} -