fix(terminal): right-pane switching + mobile soft keys #26

Merged
lz merged 2 commits from fix/right-pane-terminal-ux into main 2026-05-26 23:01:57 +02:00
Owner

Summary

Two changes to the right-pane session terminal:

  • fix(terminal): remount SessionTerminal on scope change. The WebSocket was only opened in onMount, so clicking a different session from the left pane updated the topbar but left the terminal bound to the original target. The Files-and-back workaround worked because the tab toggle unmounted the component. Wrapping <SessionTerminal> in {#key kind|worker|session} forces a clean remount per scope, which is what the existing 250ms scope debouncer in MainSplit already assumed.
  • feat(terminal): mobile soft-key row. Phones rarely emit Esc / Shift+Tab / Ctrl+C — keys Claude Code's TUI depends on. Adds a thin row between the header and the xterm body with Esc, ⇧⇥, ⇥, ⌃C, ↑, ↓. Each button sends the raw escape sequence over the existing WebSocket. Hidden on desktop via @media (max-width: 768px) (matches the existing MainSplit breakpoint). pointerdown preventDefault keeps focus on the terminal so the on-screen keyboard doesn't flap.

Test plan

  • pnpm lint — clean
  • pnpm typecheck — 840 files, 0 errors, 0 warnings
  • pnpm test — 474/474 passing
  • Manual: click between two sessions, confirm terminal contents swap (no Files-tab detour)
  • Manual: open on mobile (or DevTools mobile emulator), tap Shift+Tab to flip Claude's modes, tap Esc to clear input, tap ⌃C to interrupt
## Summary Two changes to the right-pane session terminal: - **fix(terminal): remount SessionTerminal on scope change.** The WebSocket was only opened in `onMount`, so clicking a different session from the left pane updated the topbar but left the terminal bound to the original target. The Files-and-back workaround worked because the tab toggle unmounted the component. Wrapping `<SessionTerminal>` in `{#key kind|worker|session}` forces a clean remount per scope, which is what the existing 250ms scope debouncer in `MainSplit` already assumed. - **feat(terminal): mobile soft-key row.** Phones rarely emit Esc / Shift+Tab / Ctrl+C — keys Claude Code's TUI depends on. Adds a thin row between the header and the xterm body with Esc, ⇧⇥, ⇥, ⌃C, ↑, ↓. Each button sends the raw escape sequence over the existing WebSocket. Hidden on desktop via `@media (max-width: 768px)` (matches the existing `MainSplit` breakpoint). `pointerdown preventDefault` keeps focus on the terminal so the on-screen keyboard doesn't flap. ## Test plan - [x] `pnpm lint` — clean - [x] `pnpm typecheck` — 840 files, 0 errors, 0 warnings - [x] `pnpm test` — 474/474 passing - [ ] Manual: click between two sessions, confirm terminal contents swap (no Files-tab detour) - [ ] Manual: open on mobile (or DevTools mobile emulator), tap Shift+Tab to flip Claude's modes, tap Esc to clear input, tap ⌃C to interrupt
lz added 2 commits 2026-05-26 19:22:18 +02:00
The right-pane SessionTerminal opens its WebSocket in onMount only.
Switching session or workspace from the left pane updated the topbar
label but reused the same component instance, so the WS stayed bound
to the original target. Wrap the component in {#key kind|worker|session}
so scope changes destroy the old terminal and mount a fresh one.

The 250ms scope debouncer in MainSplit already coalesced rapid clicks
on the assumption that the terminal would remount per scope — this
restores that contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(terminal): add mobile soft-key row
All checks were successful
ci / nexus (pull_request) Successful in 2m3s
ci / images (./nexus, agent-nexus) (pull_request) Successful in 3m20s
ci / images (./worker, nexus-worker) (pull_request) Successful in 50s
6ff1436062
Phones and tablets often can't emit the keys Claude Code's TUI relies
on (Esc to cancel, Shift+Tab to switch modes, Ctrl+C to interrupt).
Render a row of soft keys between the terminal header and the xterm
body — Esc, Shift+Tab, Tab, Ctrl+C, ↑, ↓ — each sending the raw
escape sequence over the existing WebSocket so xterm/tmux/claude see
no difference from a real keypress.

Hidden on desktop via @media (max-width: 768px) (matches the existing
MainSplit breakpoint). pointerdown preventDefault keeps focus on the
xterm cell so the on-screen keyboard doesn't flap on each tap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lz merged commit 86cb362180 into main 2026-05-26 23:01:57 +02:00
lz deleted branch fix/right-pane-terminal-ux 2026-05-26 23:01:57 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lz/agent-nexus!26
No description provided.