From 66867328476bf1cb835a6325f62c849d305a8973 Mon Sep 17 00:00:00 2001 From: Antisophy <293439221+Antisophy@users.noreply.github.com> Date: Fri, 21 Aug 2026 01:05:07 -0700 Subject: [PATCH] feat(web): hide the composer while reading history on narrow screens iOS pins the composer above the on-screen keyboard, then lets the two drift apart as soon as the page scrolls: the box ends up floating over a gap, and only a drag that starts inside it puts them back together. The page cannot see that drift, so there is nothing to correct against. Scrolling up to read is also the moment neither the composer nor the keyboard is wanted, so leaving the bottom of the message list now hides the composer and blurs the field, which is what actually dismisses the keyboard. Returning to the bottom brings the box back; iOS will not raise the keyboard again without a tap, so that stays manual. Hiding is display:none on a component that stays mounted, so a draft in progress survives. Scoped to the same 768px breakpoint the rest of the mobile layout uses: wider screens have room for the composer and no keyboard to dismiss. --- web/src/components/InputBox.tsx | 7 ++++++- web/src/components/MessageList.tsx | 15 +++++++++++++++ web/src/components/SessionView.tsx | 19 +++++++++++++++++++ web/src/styles.css | 7 +++++++ 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/web/src/components/InputBox.tsx b/web/src/components/InputBox.tsx index 636f49e9..515c3c40 100644 --- a/web/src/components/InputBox.tsx +++ b/web/src/components/InputBox.tsx @@ -15,6 +15,8 @@ const supportsFieldSizing = CSS.supports("field-sizing", "content"); interface CommonProps { onInterrupt: () => void; + /** narrow screens hide the composer while the reader is scrolled up */ + hidden?: boolean; isProcessing: boolean; stdinClosed?: boolean; disabled: boolean; @@ -361,6 +363,7 @@ export function InputBox(props: InputBoxProps) { function OrdinaryInputBox({ onSend, onInterrupt, + hidden = false, isProcessing, stdinClosed, disabled, @@ -527,7 +530,9 @@ function OrdinaryInputBox({ return ( ) : (