Skip to content

feat: give sessions the full height and overlay status content#14

Merged
kylecarbs merged 1 commit into
mainfrom
ui-full-height-viewport
Jun 10, 2026
Merged

feat: give sessions the full height and overlay status content#14
kylecarbs merged 1 commit into
mainfrom
ui-full-height-viewport

Conversation

@kylecarbs

Copy link
Copy Markdown
Member

The last screen row is no longer reserved for a status bar. Sessions in boo ui now get the full terminal height, and the bottom row composes like every other row: sidebar, separator, viewport.

  • The Keybinds: Ctrl+A hint moved into the sidebar's bottom row (it fits in the sidebar width), so the separator line runs all the way down.
  • Status content (rename prompt, kill confirmation, the armed-prefix keybind list, transient messages) overlays the last row full-width only while it has something to show. When it clears, the row diff cache repaints the row from sidebar and session state, restoring whatever was underneath.
  • A session cursor on the last row is hidden while the overlay shows so it does not blink over the overlay text.
  • Layout.Hit.status is gone: clicks and drags on the bottom row hit the viewport (or nothing, over the hint/separator), and mouse events there forward to the application like any other viewport row.

This came out of investigating a bottom-bar/cursor positioning issue seen with bottom-anchored TUIs (Claude Code): with a reserved bottom row the session never owned the true last row of the terminal. Removing the reservation removes that interplay entirely; please re-check the original symptom against this branch.

Validation

Dogfooded by running boo ui inside a boo session and peeking it, with an inner session that anchors an input line plus cursor at its last row (Claude Code style):

$ boo peek outer            # bottom row: hint, separator, session content
 Keybinds: Ctrl+A       │claude-input>
$ boo peek outer --json     # cursor sits on the true last row
cursor: {'row': 24, 'col': 40}

Arming C-a overlays the keybind bar across the bottom row; Esc reverts it and the cursor returns to row 24. stty size inside a session now reports the full height (24 75 in a 24x100 terminal).

zig fmt --check, zig build test, and zig build test-integration all pass.

Design notes
  • Layout.viewportRows() now returns the full height; every consumer (view sizing, resize propagation, empty-state centering, cursor clamping) follows from that single change.
  • The session list capacity is unchanged: the row the status bar used to occupy is now the sidebar hint row, so listRows() keeps the same formula.
  • The overlay needs no extra repaint plumbing: arming/disarming the prefix, prompt state changes, and message expiry already set need_render, and the per-row cache diff repaints the bottom row when its composed content changes in either direction.
  • Integration coverage: a new waitLastRow helper renders the accumulated PTY output through ghostty-vt and asserts the bottom row's contents, verifying hint+separator, the full-width overlay while armed, and the revert after Esc.

This PR was generated by Coder Agents on behalf of @kylecarbs.

The last screen row is no longer reserved for a status bar. The
keybind hint lives in the sidebar's bottom row, the separator runs
through the last row, and the viewport (and the session inside it)
spans the full terminal height.

Status content (rename prompt, kill confirmation, the armed-prefix
keybind list, transient messages) overlays the last row full-width
while present; when it clears, the row repaints from cached sidebar
and session state. A session cursor on the last row hides while the
overlay shows so it does not blink over the text.
@kylecarbs kylecarbs merged commit c734290 into main Jun 10, 2026
4 checks passed
@kylecarbs kylecarbs mentioned this pull request Jun 10, 2026
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.

1 participant