Skip to content

Scroll the desktop model picker as one region - #2310

Open
SawyerHood wants to merge 1 commit into
mainfrom
bb/fix-doobie-modal-selector-repro-thr_bih52wg67b
Open

Scroll the desktop model picker as one region#2310
SawyerHood wants to merge 1 commit into
mainfrom
bb/fix-doobie-modal-selector-repro-thr_bih52wg67b

Conversation

@SawyerHood

Copy link
Copy Markdown
Collaborator

What was wrong

The desktop model menu held two scroll regions. The popover capped itself at the Radix available height and scrolled, while the model list kept its own shrink-0 max-h-[min(250px, available - 80px)] scroller inside it (added in #1596). The 80px constant does not cover the real chrome: the provider tabs (33px), the search field (37px), the reasoning rows (189px), the fast-mode toggle (34px) and the dividers add up to ~295px. So in a short viewport the model list held its full height, the reasoning rows sat below the fold, and the wheel or touch gesture that started over the models was captured by the inner scroller instead of the popover. A user reported that the reasoning options at the bottom were unreachable after zooming in.

Measured on main at a 1000x520 viewport: the popover was 341px tall with 536px of content, and the reasoning section ended at y=681 — 161px below the viewport.

What changed

apps/app/src/components/pickers/ModelReasoningPicker.tsx gives the desktop menu a single scroll region.

  • The popover is now overflow-hidden and pins the provider tabs and the search field (shrink-0).
  • A new body element under MenuHoverProvider owns min-h-0 flex-1 overflow-y-auto overscroll-contain, so the model rows, the reasoning rows, the fast-mode toggle and the footer action scroll together.
  • The model list drops its desktop cap and its own scroller. Its sticky "Model" and "Reasoning" section labels now stick to the shared region.
  • The compact drawer path keeps its previous markup, so mobile behavior is unchanged.

Trade-off: on a tall viewport with a very long list (for example during a search), the reasoning rows are no longer pinned below a 250px model scroller. One predictable scroll region is worth more than a pin that only held while the menu fit anyway.

No wire or CLI surface changed.

How you verified

Browser checks through the doobie CLI against the dev app, Codex provider (8 models, 6 reasoning levels):

Viewport Before After
1000x520 2 scroll regions; reasoning ended 161px below the fold 1 scroll region; one wheel gesture reveals every reasoning row and Fast mode
1000x400 2 scroll regions; the whole reasoning section was off-screen 1 scroll region; clicking "Ultra" commits the level (the trigger reads 5.6-Sol Ultra)
1000x900 no scroller no scroller, menu unchanged
500x800 (compact) drawer drawer unchanged

Also confirmed the search field stays pinned during a search and that arrow-key navigation still scrolls the highlighted row into view at 1000x400.

Tests: replaced the picker's desktop scroll test with scrolls the desktop models and reasoning rows as one region, which asserts exactly one scroll region and that it contains both the models listbox and the reasoning rows. It fails on the previous code (expected [ …(2) ] to have a length of 1 but got 2) and passes now.

Commands:

  • pnpm exec turbo run typecheck --filter=@bb/app
  • pnpm exec turbo run lint --filter=@bb/app
  • pnpm exec turbo run test --filter=@bb/app (422 files, 3288 tests passed)
  • pnpm exec turbo run build --filter=@bb/app

Reported by a user over DM; no GitHub issue was open for it.

AGENT GENERATED

## What was wrong

The desktop model menu held two scroll regions. The popover capped itself
at the Radix available height and scrolled, while the model list kept its
own `shrink-0 max-h-[min(250px, available - 80px)]` scroller inside it. The
80px constant does not cover the real chrome: the provider tabs, the search
field, the reasoning rows, the fast-mode toggle and the footer action add up
to ~295px. So in a short viewport the model list held its full height, the
reasoning rows sat below the fold, and the wheel or touch gesture that
started over the models was captured by the inner scroller. A user reported
that the reasoning options at the bottom were unreachable after zooming in.

## What changed

`apps/app/src/components/pickers/ModelReasoningPicker.tsx` gives the desktop
menu a single scroll region. The popover is now `overflow-hidden` and pins
the provider tabs and the search field. A new body element under
`MenuHoverProvider` owns `min-h-0 flex-1 overflow-y-auto overscroll-contain`,
so the model rows, the reasoning rows, the fast-mode toggle and the footer
action scroll together. The model list drops its desktop cap and scroller,
which also moves its sticky section labels onto the shared region. The
compact drawer path keeps its previous markup.

## How you verified

- Reproduced in the dev app through doobie at 1000x520 and 1000x400: the
  reasoning section ended 161px below the viewport, and a wheel gesture over
  the models only moved the inner list.
- After the change, one wheel gesture reveals every reasoning option and the
  fast-mode toggle at both heights, and clicking "Ultra" at 1000x400 commits
  the level. A 1000x900 viewport still shows the whole menu with no scroller.
  The 500x800 compact drawer is unchanged.
- Replaced the picker's desktop scroll test with one that asserts a single
  scroll region containing both the models listbox and the reasoning rows.
  It fails on the previous code ("expected [ ...(2) ] to have a length of 1")
  and passes now.
- `pnpm exec turbo run typecheck lint test build --filter=@bb/app`
  (3288 tests passed).

> AGENT GENERATED
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