From a7cc903bf58bef1de6e70f9aa19ec5c4c89567fa Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Wed, 22 Apr 2026 14:28:47 -0500 Subject: [PATCH] fix(tui): breathing room above the composer cluster, status tight to input Previous revision added marginTop={1} to the input which stacked as a phantom gap BETWEEN status and input. The breathing row should sit ABOVE the status-in-top cluster, not inside it. - StatusRulePane at="top" now carries its own marginTop={1} so it always has a one-row gap above (separating it from transcript or, when queue is present, from the last queue item) - Input Box marginTop flips: 0 in top mode (status is the separator), 1 in bottom/off mode (input itself caps the composer cluster) - Net: status and input are tight together in 'top'; input and status are tight together at the bottom in 'bottom'; one-row breathing room above whichever element sits on top of the cluster --- ui-tui/src/components/appChrome.tsx | 4 +- ui-tui/src/components/appLayout.tsx | 58 ++++++++++++++++------------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/ui-tui/src/components/appChrome.tsx b/ui-tui/src/components/appChrome.tsx index 3d14f5003b0..bffcd6c5152 100644 --- a/ui-tui/src/components/appChrome.tsx +++ b/ui-tui/src/components/appChrome.tsx @@ -1,6 +1,6 @@ -import { Box, type ScrollBoxHandle, Text } from '@hermes/ink' +import { Box, Text, type ScrollBoxHandle } from '@hermes/ink' import { useStore } from '@nanostores/react' -import { type ReactNode, type RefObject, useCallback, useEffect, useMemo, useState, useSyncExternalStore } from 'react' +import { useCallback, useEffect, useMemo, useState, useSyncExternalStore, type ReactNode, type RefObject } from 'react' import { $delegationState } from '../app/delegationStore.js' import { $turnState } from '../app/turnStore.js' diff --git a/ui-tui/src/components/appLayout.tsx b/ui-tui/src/components/appLayout.tsx index 6e4119cfe1a..6cb6de59e78 100644 --- a/ui-tui/src/components/appLayout.tsx +++ b/ui-tui/src/components/appLayout.tsx @@ -184,7 +184,16 @@ const ComposerPane = memo(function ComposerPane({ {!isBlocked && ( - <> + + + {composer.inputBuf.map((line, i) => ( @@ -196,15 +205,6 @@ const ComposerPane = memo(function ComposerPane({ ))} - - {sh ? ( $ @@ -230,7 +230,7 @@ const ComposerPane = memo(function ComposerPane({ - + )} {!composer.empty && !ui.sid && ⚕ {ui.status}} @@ -264,22 +264,28 @@ const StatusRulePane = memo(function StatusRulePane({ return null } + // 'top' sits inline above the input; give it one row of breathing + // space above so the transcript (or queue) doesn't butt directly + // against the status row. 'bottom' lives at the last row of the + // viewport so it needs no margin. return ( - + + + ) })