Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

[Bug]: interactive TUI fullscreen: mouse-wheel scroll is a no-op while the transcript is following the tail

オープン 初心者向け
#481 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
72/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
typescript
領域
cli, frontend

調査の方向性

packages/tui/src/tui/engine/components/scroll-view.tsを読み、followingEndがtrueのときのscrollByを追ってください。次に、packages/tui/src/tui/engine/tui-alt-screen.tsのrouteWheel付近で、ホイール入力のルーティングを調べてください。長いトランスクリプトを使い、まず末尾に固定された状態で、次に上へスクロールした後に、全画面で再現してください。下方向のホイール入力で固定状態からトランスクリプトが移動し、ストリーミング中も引き続き動作すれば完了です。

索引モデルが issue の本文から書いたものです。

説明

bug needs-triage tui
Product or interface

CLI - interactive TUI

Version

0.6.5

Platform

Linux

OS version and architecture

Debian 12

Issue area

UI / UX

Desktop log upload ID (optional)

No response

Steps to reproduce
  1. Run the interactive TUI in fullscreen mode:
    mcode --tui-mode fullscreen
    (or switch into fullscreen at runtime, if already running in regular mode).

  2. Run inside a terminal that reports mouse input — e.g. Termius, Windows
    Terminal, iTerm2. Do NOT disable mouse reporting.

  3. Produce a transcript taller than the viewport. Either send a few messages,
    or start a turn and let the assistant stream output until the transcript
    overflows.

  4. Leave the viewport pinned to the bottom. This is the default state: the
    transcript is created with follow: 'end', so as long as you have NOT
    scrolled up, followingEnd is true.

  5. Scroll DOWN with the mouse wheel. Repeat several notches.

  6. For contrast, scroll UP once (this works), then scroll DOWN again
    (this also works).

  7. For contrast again, start a streaming turn and try scrolling down while
    tokens are arriving.

Expected and actual behavior

EXPECTED
Scrolling down with the mouse wheel moves the transcript viewport toward the
tail, and scrolling up moves it back through the history — at the same
granularity the terminal is configured for, with acceleration.

ACTUAL
While the transcript is in the follow-tail state (the default), downward
mouse-wheel input produces no movement at all. No error, no partial repaint,
no visual feedback whatsoever — the wheel simply appears dead.

Upward wheel input works, and downward wheel input also works once the
viewport has been scrolled up at least once. So the failure is specific to
the follow-tail state, not to the wheel in general.

While output is streaming, the dead state reappears, because the viewport is
re-pinned to the tail on every layout pass.

WHY IT LOOKS INTERMITTENT
The wheel is only ignored when followingEnd happens to be true. Any upward
scroll clears it; any layout pass during streaming sets it again. So the same
gesture works or does nothing depending on invisible state the user cannot
observe.

ROOT-CAUSE HYPOTHESIS (from reading the source, not yet instrumented)

packages/tui/src/tui/engine/components/scroll-view.ts:150

scrollBy(lines: number): number {
  ...
  const start = this.followingEnd ? maxScrollTop : this.currentScrollTop;
  const next = Math.max(0, Math.min(maxScrollTop, start + requested));
  const moved = next - start;
  ...
  return requested - moved;
}

When followingEnd is true the scroll start position is forced to
maxScrollTop, so a downward wheel yields moved === 0, and the function
returns the full requested amount as "unconsumed".

packages/tui/src/tui/engine/tui-alt-screen.ts:731-743 (routeWheel) then
discards that remainder:

for (const scrollView of getScrollViewsAt(layout, x, y)) {
  remaining = scrollView.scrollBy(remaining);
  if (remaining === 0 || scrollView.overscroll === "contain") break;
}

The transcript viewport is created with follow: 'end' and
overscroll: 'contain':

packages/tui/src/tui/features/transcript/panel.ts:125-129
packages/tui/src/tui/shell/chat-layout.ts:152-158

followingEnd is only ever cleared by an upward scroll
(scroll-view.ts:155). Downward wheel input is never treated as a user
override of the follow-tail state — so it can never move the viewport.

In other words, the sticky/follow state is modelled as authoritative over
user input, rather than as a render default that user input overrides.

SECONDARY OBSERVATIONS (separate from the dead-scroll bug)

a) Wheel granularity is hardcoded to one line.

 packages/tui/src/tui/engine/tui-alt-screen.ts:249
   this.wheelScrollLines = Math.max(1, Math.floor(options.wheelScrollLines ?? 1));

 `wheelScrollLines` is declared in `TuiAltScreenOptions` but no caller in
 this repository ever passes it, and there is no CLI flag or environment
 variable for it. xterm.js-derived terminals (Termius, Windows Terminal,
 iTerm2) emit one wheel event per notch, so the wheel moves exactly one
 line per notch with no acceleration. Even when the wheel does work, a
 transcript of several hundred lines is effectively unscrollable by wheel.

b) There is no escape hatch to disable mouse reporting.

 Once the fullscreen renderer enables mouse tracking, the terminal stops
 doing its own scrollback and every wheel event is delivered to the TUI.
 `TuiAltScreenOptions.mouse` exists
 (packages/tui/src/tui/engine/tui-alt-screen.ts:173) but is not wired to
 any CLI flag or environment variable. For comparison, Claude Code exposes
 `CLAUDE_CODE_DISABLE_MOUSE` and additionally auto-disables fullscreen
 under `tmux -CC` because "mouse wheel is dead" there.

SUGGESTED FIX DIRECTION (no patch attached)

  1. Treat wheel input as a user override. Clear the follow-tail flag before
    applying a wheel delta, instead of using it to choose the scroll start
    position. This is the minimal change and removes the dead state entirely.

  2. Longer term, separate the two concepts the way ink's ScrollBox does:
    keep scrollTop as the real position and stickyToEnd as a render-time
    default. Any explicit user scroll clears stickyToEnd
    (el.stickyScroll = false; el.scrollAnchor = undefined;) before moving.

  3. Wire wheelScrollLines to a setting, and add momentum/accumulation so
    fast flicks produce intermediate frames instead of 1:1 line stepping.

  4. Expose an environment variable or flag to disable mouse reporting, and
    consider auto-disabling it under multiplexers, so users can fall back to
    native terminal scrollback.

Redacted error summary
None. No error is emitted; the input is consumed and the resulting scroll
delta is discarded internally.
Screenshots

A short screen recording is more useful than a still here, since the failure
is "nothing happens":

  • Start in fullscreen TUI with a transcript taller than the viewport.
  • Scroll DOWN without scrolling up first -> no movement.
  • Scroll UP once, then scroll DOWN -> movement resumes.

Attach the recording to this field (not to the code-formatted field above).

Before submitting
  • I have searched existing issues.
  • I have included my version and removed sensitive information.
主要言語
TypeScript
スター
2k
フォーク
254
平均マージ
8時間 35分
マージ済み PR(30日)
152

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

MiniMax-AI/minimax-code のほかの issue

MiniMax-AI/minimax-code の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。