Skip to content

[Bug] Multiselect leaves a stale prompt fragment after terminal resize with wrapped hints #625

Open

Description

@valentinpalkovic

Environment

  • OS: Ubuntu 24.04.5
  • Node Version: 24.21.0
  • Package: @clack/prompts
  • Package Version: 1.8.1

Describe the bug
A multiselect prompt with long option hints leaves part of its previous frame at the top of the terminal after a width change and a navigation keypress. The active prompt continues to respond to Down and Ctrl-C, but the old text remains visible above it.

I reproduced this in a standalone @clack/prompts app with version 1.8.1, independent of Storybook. It occurs in tmux and in an xterm.js 5.5.0 PTY replay.

To Reproduce
package.json:

{"private":true,"type":"module","dependencies":{"@clack/prompts":"1.8.1"}}

repro.mjs

import { multiselect } from '@clack/prompts';

const options = [
  'eslintPlugin',
  'component-subtitle',
  'argtypes-default-value',
  'story-sort-to-main',
  'remove-experimental-review',
  'skills',
].map((label) => ({
  value: label,
  label,
  hint: `Move deprecated parameters.componentSubtitle values to parameters.docs.subtitle\nMore info: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#parameterscomponentsubtitle-removed`,
}));

await multiselect({
  message: 'Select automigrations to run',
  options,
  initialValues: ['eslintPlugin'],
  required: false,
});

Run npm install --no-audit --no-fund and node repro.mjs in a 120x40 terminal. Resize to 40x30, then press Down. A fragment of the old prompt stays at the top. Resize to 80x24 and press Down; the fragment persists. The current selection still moves, and Ctrl-C still works.

For a deterministic tmux replay:

tmux -L clack-resize new-session -d -x 120 -y 40 -s repro 'node repro.mjs'
tmux -L clack-resize resize-window -t repro -x 40 -y 30
tmux -L clack-resize send-keys -t repro Down
tmux -L clack-resize capture-pane -t repro -p
tmux -L clack-resize resize-window -t repro -x 80 -y 24
tmux -L clack-resize send-keys -t repro Down
tmux -L clack-resize capture-pane -t repro -p

Expected behavior
After each resize and redraw, the old prompt frame is fully cleared and only the current prompt is visible.

** Actual behavior **
The top row retains a fragment of the prior, wider frame (for example, the end of parameters.docs.subtitle). The current frame is drawn below it. The problem remains after widening the terminal again.

Additional Information

  • Ubuntu 24.04.5; Node 24.21.0; npm 11.19.0; TERM=xterm-256color.
  • Reproduced in tmux and in xterm.js 5.5.0.
  • @clack/prompts 1.0.0-alpha.7 and 1.8.1 both reproduce.
  • The renderer appears to recalculate the previous frame's wrapping using the new terminal width when erasing. Wrapped rows that have scrolled above the viewport cannot then be erased. The multiselect viewport also appears to count options without accounting for all visual rows used by wrapped hints. These are hypotheses from the reproducer, not a confirmed fix.

Related: PR #577 addresses multiselect line counts on narrow terminals, but I have not verified this resize sequence against that PR.

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 isn't working

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions