Skip to content

fix(mobile): new-session composer spacing and session bottom-inset surface - #4774

Merged
iscekic merged 4 commits into
mainfrom
fix/mobile-layout-nits
Jul 27, 2026
Merged

fix(mobile): new-session composer spacing and session bottom-inset surface#4774
iscekic merged 4 commits into
mainfrom
fix/mobile-layout-nits

Conversation

@iscekic

@iscekic iscekic commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

What

Two iOS-visible fixes on the Agents surfaces.

New session screen — dead space under the attachment/microphone row

The prompt card reserved 24pt of permanently empty space between the action row and the model/mode toolbar: a min-h-[20px] wrapper around VoiceInputStatus, which renders null in every status except listening (the reservation was introduced in 863d6ff so toggling voice input could not shift the composer layout).

The "Listening…" caption now renders inline as the middle child of the action row, inside a height-pinned h-9 wrapper (the same 36pt as the flanking paperclip/microphone controls) with overflow-hidden, so the row height is set by the controls and cannot change when the caption appears — at any Dynamic Type scale. The reserved block is deleted and the row's bottom padding becomes pb-2, matching the card's existing pt-2 top inset.

Session screen — bottom safe-area strip matches the composer surface

The strip below the composer was a solid bg-background view while the composer above it is a BlurBar (expo-blur, intensity 40). A tinted blur over bg-background does not resolve to bg-background — measured delta (−4,−4,−4) per channel in dark theme.

When the composer is the bottom-most visible element, the strip now renders the same BlurBar surface (border-t-0, verified to merge away the hairline via twMerge). The solid bg-background strip stays for the blocking question/permission cards, and the strip's placement after the KeyboardAvoidingView — which keeps the composer flush on the open keyboard — is unchanged. Android is unaffected (BlurBar already resolves to bg-background there).

Deliberately out of scope: the read-only-session banner (bg-secondary) also sits above a bg-background strip; that surface is unchanged.

Verification

  • From apps/mobile/: pnpm format && pnpm typecheck && pnpm lint && pnpm check:unused && pnpm test (1871/1871 passing) and git diff --check.
  • On-device E2E (iPhone 17 / iOS 26.5): action-row→toolbar spacing measurement, voice-toggle no-layout-shift check, and composer/strip pixel sampling in light and dark themes — evidence follows in a comment.

@iscekic iscekic self-assigned this Jul 26, 2026
@iscekic

iscekic commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

(bot) On-device E2E verification (iPhone 17 / iOS 26.5 simulator, this worktree's stack, bundle provenance validated). Baseline numbers from the confirmed reproduction on the unmodified code.

New-session action-row gap — PASS. Attachment-row bottom → toolbar top measured from the Maestro hierarchy: 8pt in all four combinations of keyboard open/closed × light/dark (baseline 24pt; acceptance ≤12pt). Everything else on the screen matches baseline.

Session bottom strip vs composer surface — PASS. Full-width row-average sampling, keyboard closed: light Δ(−0.07, 0, 0), dark Δ(0, 0, 0) per channel (baseline: light (0,−1,+1), dark (−4,−4,−4)). Within the |Δ| ≤ 2 tolerance in both themes, dark strictly improved to exact equality, and no visible seam, hairline, or tonal step in either theme.

Read-only banner state — PASS (unchanged). On a read-only session with messages, the strip below the banner samples as the solid screen background in both themes (dark (14,14,16) = --background #0e0e10; light ≈ (251,250,245)) — exactly what the baseline rendered; that state takes the untouched bg-background branch. Question/permission blocking-card states likewise take the untouched branch (inspection). Zero-inset devices render a zero-height strip in both branches (inspection). Android unaffected (BlurBar already falls back to bg-background; code path read, no device run).

Two states are environment-blocked, not silently passed:

  1. Voice listening on the new-session screen. The simulator's speech recognizer never reaches listening (no permission prompt appears; the control stays Start voice input) — a known simulator limitation. Structural proof of the no-layout-shift property instead: the caption renders inside a fixed h-9 wrapper, the same height as the flanking paperclip/microphone controls, so the action row's height is pinned by the controls and is status-independent by construction at any Dynamic Type scale; overflow-hidden clips instead of expanding.
  2. Keyboard-open geometry on the session-detail composer. The software keyboard could not be raised on the session-detail screen in this environment — with the hardware keyboard disabled and tap-to-focus verified working on two other screens of the same app (new-session prompt, Agents search). Every available session type was tried (stale cloud-agent, inactive CLI → read-only, live CLI with relay → still resolves read-only, fresh cloud session → requires a GitHub repo the account lacks). Crucially, the baseline reproduction on the unmodified code hit the identical wall (its "keyboard-open" captures show the keyboard-closed layout with the composer at the same Y), so no before/after comparison is obtainable in this environment. The regression guard is instead satisfied structurally: the diff does not touch the KeyboardAvoidingView, the composer, or any focus/keyboard code, and the strip keeps the exact same frame (height = bottom inset, same sibling position after the KAV), so the KAV padding math that lands the composer flush on the keyboard is invariant under this change. The keyboard-closed geometry was verified to match baseline exactly (composer [0,777]–[402,840], strip [0,840]–[402,874]).

Checks run at the barrier from apps/mobile/: pnpm format && pnpm typecheck && pnpm lint && pnpm check:unused && pnpm test (1871/1871) and git diff --check — all green. A fresh reviewer pass over the full diff reported no findings.

@Kilo-Org Kilo-Org deleted a comment from kilo-code-bot Bot Jul 26, 2026
@iscekic

iscekic commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

(bot) Standin review of head 1a30ac560 — this is not a Kilobot review. It is posted because the automated Kilo Code Review pipeline posts nothing on PRs in this repository (the Kilo Code Review status check is green but carries no findings or summary, and the bot account confirms it cannot trigger the review summary). This review was produced independently by the mobile workflow's read-only reviewer role over the full PR diff (git diff origin/main...HEAD), so a review is on the record.

Result: No findings.

Evidence verified during the review:

  • new-session-prompt.tsx: VoiceInputStatus renders null in every status except listening; the caption now sits in a fixed h-9 + overflow-hidden flex-1 wrapper between the two h-9 controls, so the action row cannot change height when the caption appears, at any Dynamic Type scale. pb-2 matches the card's existing pt-2 top inset; the min-h-[20px] reserved block is fully deleted with no remnant; when voice input is unavailable the row degrades to paperclip-only exactly as before.
  • session-detail-content.tsx: isComposerMounted is verbatim the previous inline mount condition and the blocking-interaction hide mechanism is untouched, so the BlurBar strip appears exactly when the composer is the bottom-most visible element; blocking question/permission cards and the read-only banner keep the solid bg-background strip; strip placement after the KeyboardAvoidingView is unchanged; on Android BlurBar falls back to a bg-background view, visually identical to before.
  • The border-t-0 hairline removal was confirmed against the installed tailwind-merge 3.5.0: border-t-[0.5px] and border-t-0 share the border-w-t class group, so cn() keeps border-t-0 on both the iOS BlurView and Android fallback branches.

Residual testing risks (recorded, non-blocking):

  • Blur continuity between the adjacent blur views is covered by the on-device pixel-sampling E2E on the tested iOS version; there is no automated guard against seam artifacts on other iOS versions.
  • The 36pt action-row height invariant is covered by the E2E voice-toggle run, not by an automated layout assertion; a future change to the action row could regress it silently.

@iscekic
iscekic enabled auto-merge (squash) July 26, 2026 15:54
@iscekic
iscekic disabled auto-merge July 26, 2026 15:58
@iscekic
iscekic merged commit 47db332 into main Jul 27, 2026
19 checks passed
@iscekic
iscekic deleted the fix/mobile-layout-nits branch July 27, 2026 09:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants