Skip to content

fix(tui): scroll long picker lists so they don't overflow the viewport#978

Open
gewenyu99 wants to merge 9 commits into
mainfrom
posthog-code/scroll-picker-menu
Open

fix(tui): scroll long picker lists so they don't overflow the viewport#978
gewenyu99 wants to merge 9 commits into
mainfrom
posthog-code/scroll-picker-menu

Conversation

@gewenyu99

@gewenyu99 gewenyu99 commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

We have wayyyy too many choices. There is a separate fix for the wizard to not surface like 30 options at once, but pagination meanwhile so it doesn't overflow
Before:
image

Now:

Screen.Recording.2026-07-24.at.8.46.03.PM.mov

Single-column PickerMenu (single- and multi-select) rendered every option
unconditionally, so a long list — e.g. the self-driving "connected tools"
multi-select with 30+ options — overflowed the terminal and pushed the
Confirm button off screen.

Add terminal-height-aware windowing to PickerMenu, mirroring the existing
GroupedPickerMenu pattern: a usePickerViewport hook derives a row budget from
the terminal height, scrolls the visible window to keep the focused row in
view, and renders "↑/↓ N more" indicators. Windowing engages only for
single-column pickers that don't fit; short lists and multi-column grids
render exactly as before.

Generated-By: PostHog Code
Task-Id: f40c1784-7368-4811-83d0-2d69a844b6c5
@github-actions

Copy link
Copy Markdown

🧙 Wizard CI

Run the Wizard CI and test your changes against wizard-workbench example apps by replying with a GitHub comment using one of the following commands:

Test all apps:

  • /wizard-ci all

Test all apps in a directory:

  • /wizard-ci basic-integration
  • /wizard-ci mcp-analytics
  • /wizard-ci revenue

Test an individual app:

  • /wizard-ci basic-integration/android
  • /wizard-ci basic-integration/angular
  • /wizard-ci basic-integration/astro
Show more apps
  • /wizard-ci basic-integration/django
  • /wizard-ci basic-integration/fastapi
  • /wizard-ci basic-integration/flask
  • /wizard-ci basic-integration/javascript-node
  • /wizard-ci basic-integration/javascript-web
  • /wizard-ci basic-integration/laravel
  • /wizard-ci basic-integration/next-js
  • /wizard-ci basic-integration/nuxt
  • /wizard-ci basic-integration/python
  • /wizard-ci basic-integration/rails
  • /wizard-ci basic-integration/react-native
  • /wizard-ci basic-integration/react-router
  • /wizard-ci basic-integration/sveltekit
  • /wizard-ci basic-integration/swift
  • /wizard-ci basic-integration/tanstack-router
  • /wizard-ci basic-integration/tanstack-start
  • /wizard-ci basic-integration/vue
  • /wizard-ci mcp-analytics/custom-dispatcher
  • /wizard-ci mcp-analytics/typescript-sdk
  • /wizard-ci revenue/stripe

Results will be posted here when complete.

gewenyu99 and others added 8 commits July 24, 2026 17:54
The Input demo's multi-select had only 4 options, so it never triggered
PickerMenu's viewport windowing. Add a MultiLong step with 30+ options so the
playground demonstrates the scroll indicators and cursor-following window
introduced in this PR.

Generated-By: PostHog Code
Task-Id: f40c1784-7368-4811-83d0-2d69a844b6c5
The scroll window sized itself to the full terminal height, so on a tall
terminal a long picker filled the whole viewport. Clamp the visual budget
to 12 rows in PickerMenu and GroupedPickerMenu, keeping known breathing
room above and below regardless of terminal size.

Generated-By: PostHog Code
Task-Id: 64dfb953-a7c2-44d2-a241-89f06bf7e4f7
PromptLabel rendered an empty row when no message was set, and the multi
picker always added marginTop below it, so ask-modal pickers (which render
the prompt in the modal body) opened with four blank lines before the first
option. Render no label row without a message and gate the marginTop on it.

Generated-By: PostHog Code
Task-Id: 64dfb953-a7c2-44d2-a241-89f06bf7e4f7
Renders the WizardAskScreen composition (ModalOverlay + paragraph +
label-less picker) across four variants — long scrolling multi-select,
multi-select with descriptions, single-select, and GroupedPickerMenu —
so height capping and spacing are eyeballable in the playground. Also
gate GroupedPickerMenu's label marginTop on an actual message, matching
PickerMenu.

Generated-By: PostHog Code
Task-Id: 64dfb953-a7c2-44d2-a241-89f06bf7e4f7
… keys

The scroll window kept offset state and threaded scrollTo through every
navigation handler. Derive the visible page from the focused index instead:
no state, ↑/↓ flip pages as focus crosses an edge, and n/p jump a whole
page (advertised in the hints bar and the "more" indicators). Also dedupe
LONG_OPTIONS into a shared export.

Generated-By: PostHog Code
Task-Id: 64dfb953-a7c2-44d2-a241-89f06bf7e4f7
Reaching Confirm in a long multi-select meant walking the whole list (or
knowing the hidden up-wrap). Bind s to submit the current selection from
anywhere, in both MultiPickerMenu and GroupedPickerMenu, advertised in the
hints bar. Pages now hold a fixed option count sized to the tallest row,
replacing per-option cost chunking with arithmetic. Key the demo pickers
per step so selection state doesn't bleed between steps.

Generated-By: PostHog Code
Task-Id: 64dfb953-a7c2-44d2-a241-89f06bf7e4f7
Drop the s-submit shortcut. In paged pickers ↑/↓ no longer walk the whole
list: they move within the visible page, and stepping past either edge
lands on the Confirm button. Pages change only via n/p. Single-select
wraps within the page. The up/down handlers collapse to one direction-
parameterized path.

Generated-By: PostHog Code
Task-Id: 64dfb953-a7c2-44d2-a241-89f06bf7e4f7
"↑ 10 more [P] for previous page" / "↓ 27 more [N] for next page".

Generated-By: PostHog Code
Task-Id: 64dfb953-a7c2-44d2-a241-89f06bf7e4f7
@gewenyu99
gewenyu99 marked this pull request as ready for review July 25, 2026 00:47
@gewenyu99
gewenyu99 requested a review from a team as a code owner July 25, 2026 00:47
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