Skip to content

[Bug]: Native Android terminal jumps upward when the keyboard opens #14464

Open

Description

@yqecea

Area

apps/mobile

Steps to reproduce

  1. Open a running terminal in the native Android T3 Code app.
  2. Tap the terminal to open the software keyboard.
  3. Repeat hiding and opening the keyboard, including while a full-screen agent CLI is running.

Expected behavior

The terminal and keyboard accessory move with the keyboard, keeping the current input visible without an abrupt upward jump.

Actual behavior

The terminal suddenly jumps upward as the keyboard opens. This is user-observed on native Android. I could not verify the animation on a device because device access is disabled in the current agent environment.

Impact

Major degradation during terminal input on a phone.

Version and investigation

The installed mobile version is unknown. Source inspection used main at c2fa9fc.

ThreadTerminalRouteScreen.tsx computes terminalBottomInset from useKeyboardState and immediately applies it as paddingBottom to the terminal container. In the pinned keyboard-controller source, that hook updates on keyboardWillShow and keyboardDidHide, whereas KeyboardStickyView follows animated keyboard height. Applying the final inset before the keyboard animation is an investigation lead, not a confirmed root cause. I have not patched it without native animation evidence.

Please check opening, closing, interactive dismissal, orientation changes and a second desktop view attached to the same PTY. This report concerns the native Android terminal, not the mobile web scrolling bug #2141. Android terminal input lag is already tracked in #12756 and software Backspace in #8253.

Workaround

No reliable workaround found.

Activity

  1. juliusmarminge commented on Sep 30, 2026

    @juliusmarminge
    Member

    Triage

    This is a real Android layout bug, and it's still there on main at c2fa9fc. It's not a duplicate of #2141 (open issue, mobile-web terminal scrolling), #12756 (open issue, per-keystroke echo delay), or #8253 (open issue, Backspace with FUTO). There's no device recording and the app version is unknown, but the jump follows directly from how the keyboard inset is applied today.

    Opening the keyboard. ThreadTerminalRouteScreen makes room by adding useKeyboardState().height plus the 52 px accessory into terminalBottomInset and applying that as paddingBottom on the terminal container. In react-native-keyboard-controller 1.21.13, useKeyboardState only updates on keyboardWillShow and keyboardDidHide. On Android, keyboardWillShow fires at the start of the show animation with the final keyboard height, so the terminal snaps to its final size on the very first frame. In that same frame the Android bottom bar unmounts and the navigation-bar padding goes away. The accessory toolbar, on the other hand, lives in KeyboardStickyView and follows the animated keyboard height. So the toolbar glides up with the keyboard while the terminal has already jumped. Because KeyboardProvider is edge-to-edge, the window doesn't resize by itself; this padding change is the only thing making room, and it happens all at once.

    Knock-on effect on the PTY. That snap also resizes the terminal. T3TerminalView.onSizeChanged reports the new row count and handleResize calls terminal.resize, so a full-screen CLI reflows immediately, and any other client attached to the same PTY gets the size change too (see #14463).

    Closing the keyboard. This is jumpy in the other direction. keyboardWillHide dismisses the accessory right away, so the toolbar disappears at the start of the animation, but useKeyboardState ignores that event. The padding stays at the open height until keyboardDidHide, then snaps back and the bottom bar remounts. With an interactive dismiss, KeyboardStickyView follows your finger while the terminal padding stays stuck until the gesture ends.

    How the chat screen avoids it. ThreadDetailScreen keeps the composer inside KeyboardStickyView and doesn't position it from useKeyboardState height. The keyboard-controller's Android callback also defers its animated start event specifically because a synchronous layout change at that moment can cancel the keyboard animation, and the terminal padding update is exactly that kind of change.

    Fix direction. Move the terminal viewport with the animated keyboard inset, and send the PTY resize once the animation has settled rather than on every size change. On a device, it's worth checking open, close, interactive dismiss, orientation changes, and a second client attached to the same PTY.

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Sep 30, 2026
  3. added
    needs more infoInitial triage showed no bug. Awaiting more info
    and removed
    needs more infoInitial triage showed no bug. Awaiting more info
    on Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions