From 7c59e1a87114de5ec6d7c53253a992e4159998e5 Mon Sep 17 00:00:00 2001 From: Ari Lotter Date: Thu, 23 Apr 2026 23:28:49 -0400 Subject: [PATCH] fix(tui): keep FloatingOverlays visible when input is blocked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FloatingOverlays (SessionPicker, ModelPicker, SkillsHub, pager, completions) was nested inside the !isBlocked guard in ComposerPane. When any overlay opened, isBlocked became true, which removed the entire composer box from the tree — including the overlay that was trying to render. This made /resume with no args appear to do nothing (the input line vanished and no picker appeared). Since 99d859ce (feat: refactor by splitting up app and doing proper state), isBlocked gated only the text input lines so that approval/clarify prompts and pickers rendered above a hidden composer. The regression happened in 408fc893 (fix(tui): tighten composer — status sits directly above input, overlays anchor to input) when FloatingOverlays was moved into the input row for anchoring but accidentally kept inside the !isBlocked guard. so here, we render FloatingOverlays outside the !isBlocked guard inside the same position:relative Box, so overlays stay visible even when text input is hidden. Only the actual input buffer lines and TextInput are gated now. Fixes: /resume, /history, /logs, /model, /skills, and completion dropdowns when blocked overlays are active. --- ui-tui/src/components/appLayout.tsx | 90 +++++++++++++++-------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/ui-tui/src/components/appLayout.tsx b/ui-tui/src/components/appLayout.tsx index 164ef5dd4..19bc7736b 100644 --- a/ui-tui/src/components/appLayout.tsx +++ b/ui-tui/src/components/appLayout.tsx @@ -185,56 +185,58 @@ const ComposerPane = memo(function ComposerPane({ - {!isBlocked && ( - - + + - {composer.inputBuf.map((line, i) => ( - - - {i === 0 ? `${ui.theme.brand.prompt} ` : ' '} + {!isBlocked && ( + <> + {composer.inputBuf.map((line, i) => ( + + + {i === 0 ? `${ui.theme.brand.prompt} ` : ' '} + + + {line || ' '} + + ))} + + + + {sh ? ( + $ + ) : ( + + {composer.inputBuf.length ? ' ' : `${ui.theme.brand.prompt} `} + + )} - {line || ' '} - - ))} + + {/* subtract NoSelect paddingX={1} (2 cols) + pw so wrap-ansi and cursorLayout agree */} + - - - {sh ? ( - $ - ) : ( - - {composer.inputBuf.length ? ' ' : `${ui.theme.brand.prompt} `} - - )} - - - - {/* subtract NoSelect paddingX={1} (2 cols) + pw so wrap-ansi and cursorLayout agree */} - - - - + + + - - - )} + + )} + {!composer.empty && !ui.sid && ⚕ {ui.status}}