fix(mobile): browser composer keyboard handling on chat and draft screens

Mobile browsers don't shrink the layout for the keyboard, so the
fullscreen composer is now pinned to the visual viewport (fixed at its
offset and height, tracked as the browser pans) instead of overflowing
underneath it; the draft screen's normal composer gets the same pinning
anchored to the visible bottom via a rAF tracker, since Safari's own
focused-field reveal proved unreliable there after leaving fullscreen.
The draft and empty-session roots drop their transform-gpu (a transform
would make them the containing block for the pinned form), the app
header hides while the browser fullscreen composer is up (the form can't
out-stack it from inside the composer wrapper's stacking context), and
leaving fullscreen nudges the still-focused field back into view.
Draft starter chips now hide while the keyboard is open in browsers too,
via an oc-browser-keyboard-open root class driven by composer focus.
This commit is contained in:
Bohdan Triapitsyn
2026-07-05 09:14:55 +03:00
parent ed07e7de18
commit b09e073e86
4 changed files with 131 additions and 4 deletions
@@ -806,7 +806,10 @@ export const ChatContainer: React.FC<ChatContainerProps> = ({ autoOpenDraft = tr
if (!currentSessionId && draftOpen) {
return (
<div className="relative flex h-full flex-col bg-background transform-gpu">
// No transform on this root: it would become the containing block for
// the fullscreen composer's position:fixed visual-viewport pinning in
// mobile browsers (see ChatInput's composerFormRef effect).
<div className="relative flex h-full flex-col bg-background">
{useCompactDraftLayout && !isDesktopExpandedInput ? (
<div className="oc-draft-center flex min-h-0 flex-1 flex-col items-center justify-center px-6 text-center">
<h1 className="text-balance text-3xl font-normal tracking-tight text-foreground">
@@ -901,7 +904,9 @@ export const ChatContainer: React.FC<ChatContainerProps> = ({ autoOpenDraft = tr
if (sessionMessages.length === 0 && !sessionIsWorking) {
return (
<div className="relative flex flex-col h-full bg-background transform-gpu">
// No transform here either — same fixed-positioning constraint as the
// draft branch above.
<div className="relative flex flex-col h-full bg-background">
{returnToParentButton}
<div
className={cn(