fix(tui): picker polish — stable height, inverse-bold selection, dropdown pinned#13592
Conversation
There was a problem hiding this comment.
Pull request overview
Improves Hermes TUI picker UX by preventing the /model picker from changing height while scrolling and by standardizing higher-contrast selection styling across pickers/prompts.
Changes:
- Make
ModelPickerlayout height stable by always rendering warning/hint rows and padding the visible list to a fixed row count. - Update selection styling in pickers/prompts to use
inverse + boldwith accent colors for clearer contrast. - Ensure
SessionPickermeta column reflects selection state (no longer always dim).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| ui-tui/src/components/modelPicker.tsx | Stabilizes picker height via unconditional slots and fixed VISIBLE row rendering; updates selection styling. |
| ui-tui/src/components/sessionPicker.tsx | Updates selection styling across all columns so the entire row reflects selection state. |
| ui-tui/src/components/skillsHub.tsx | Updates category/skill selection styling to the new inverse+bold accent approach. |
| ui-tui/src/components/prompts.tsx | Updates Approval/Clarify option selection styling to inverse+bold for higher contrast. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
dbbf1f4 to
d042fb3
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 26 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
0967f33 to
ced2de7
Compare
Warning row, "↑ N more" / "↓ N more" hints, and the items list were all conditionally rendered, so the picker jumped in size as the selection moved or providers without a warning slid into view. Render every slot unconditionally: warning falls back to a blank line, hints render an empty string when at the edge, and the items grid always emits VISIBLE rows padded with blanks. Height is now constant across providers, model counts, and scroll position.
Selected rows in the model/session/skills pickers and approval/clarify prompts only changed from dim gray to cornsilk, which reads as low contrast on lighter themes and LCDs (reported during TUI v2 blitz). Switch the selected row to `inverse bold` with the brand accent color across modelPicker, sessionPicker, skillsHub, and prompts so the highlight is terminal-portable and unambiguous. Unselected rows stay dim. Also extends the sessionPicker middle meta column (which was always dim) to inherit the row's selection state.
f091dff to
71e8d66
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 25 out of 25 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
A6 added a fixed-height grid (Array.from({length: VISIBLE})), but the
row <Text> itself had no wrap prop so Ink defaulted to wrap="wrap".
A sufficiently long model or provider name would wrap to a second
visual line and bounce the overall picker height right back — which
is exactly what reappeared during the TUI v2 blitz retest on /model.
Pin every picker row (and the empty-state / padding rows) to
wrap="truncate-end" so each slot is guaranteed one line. Applies
across modelPicker, sessionPicker, and skillsHub.
The completion popup (e.g. typing `/model`) grew from 8 rows at compIdx=0 up to 16 rows at compIdx≥8 — the slice end was `compIdx + 8` so every arrow-down added another rendered row until the window filled. Reported during TUI v2 retest: "as i scroll and more options appear, for some reason more options appear and it expands the height". Fixed viewport (`COMPLETION_WINDOW = 16`) centered on compIdx, clamped so it never slides past the array bounds. Renders exactly `min(WINDOW, completions.length)` rows every frame.
71e8d66 to
34f24da
Compare
…-polish fix(tui): picker polish — stable height, inverse-bold selection, dropdown pinned
…-polish fix(tui): picker polish — stable height, inverse-bold selection, dropdown pinned
…-polish fix(tui): picker polish — stable height, inverse-bold selection, dropdown pinned
…-polish fix(tui): picker polish — stable height, inverse-bold selection, dropdown pinned
…-polish fix(tui): picker polish — stable height, inverse-bold selection, dropdown pinned
…-polish fix(tui): picker polish — stable height, inverse-bold selection, dropdown pinned
From TUI v2 blitz-test feedback: "
/modelswitching pop-up changes in size whilst scrolling", "Contrast on highlighted items in TUI slash menus are a bit low contrast", and during retest "this dropdown box.. as i scroll and more options appear, for some reason more options appear and it expands the height".Three related tweaks landing together because they all touch the picker UX surface and share the same root concern (stable height + readable selection).
Summary
↑/↓ morehints, and the items list were all conditionally rendered, so the picker jumped as selection moved or providers without a warning slid into view. Every slot now renders unconditionally: warning falls back to a blank line, hints render an empty string at the edge, and the items grid always emitsVISIBLErows padded with blanks.<Text>itself had nowrapprop so Ink defaulted towrap="wrap". Long model/provider names wrapped to a second visual line and bounced the height right back. Every picker row (plus padding / empty-state) is nowwrap="truncate-end". Same treatment applied tosessionPickerandskillsHub.FloatBoxusesalignSelf="flex-start"so it shrinks-to-fit. Without a width constraint,truncate-endhad nothing to truncate against and the float grew/shrank as long rows scrolled into view. Pinned the outer Box to a stable width derived from terminal cols./model) grew from 8 rows atcompIdx=0to 16 atcompIdx≥8because the slice end scaled withcompIdxinstead of being a fixed window. Now a fixedCOMPLETION_WINDOW = 16rows, centered oncompIdx, clamped to array bounds.inverse boldwith the brand accent.sessionPicker's middle meta column (previously always dim) now inherits the row's selection state.Test plan
npm run type-checkcleannpm test— 152/152 pass/modelpicker, scroll — both axes stay rigid, selection is high-contrast/modelwith the dropdown visible, hold Down — stays at 16 rows, does not grow/model ha(filter down to ~2) — dropdown shrinks only from the filter, not from scroll/resume(session picker),/skills(skills hub), approval prompt, clarify prompt — selection consistent