Skip to content

feat(header): list tabs that do not fit behind a More button instead of shrinking them - #3199

Merged
devswha merged 7 commits into
mainfrom
feat/tab-overflow-more
Nov 6, 2026
Merged

devswha merged 7 commits into
mainfrom
feat/tab-overflow-more

Conversation

@devswha

@devswha devswha commented Nov 6, 2026 •

Copy link
Copy Markdown
Owner

What

On a desktop window the header's tab row (#3156) shared its width among every tab, down to 44 px each. With many tabs, the close (×) became most of a tab, so a click meant to open a tab often closed it.

Now:

  • A tab in the header row is never narrower than 120 px (lib/tabOverflow.ts TAB_MIN_WIDTH, matched in styles.css).
  • Tabs that do not fit wait behind a More button after + (a chevron and the count, e.g. ▾ 16). Its list shows each hidden tab with its agent mark and state, as the phone's tab sheet does. Picking one opens it in the row.
  • The open tab is always in the row: it takes the last place when it is past the others.
  • The close still shows only on the open tab and a hovered one, and now always on a full-size tab.
  • A split half's own strip keeps scrolling sideways (Tabs past the end of a full tab strip cannot be reached with a mouse #1515, fix(tabs): follow-ups from the wheel-scroll review (#2095) #2103), and a phone keeps its tab sheet.
  • Dragging a tab to reorder it maps the drop to its place among all the tabs: right after the drawn tab before the line (drawnTabBoundary), so a drop into the gap where tabs are hidden lands where the line shows.
  • A tab whose name is being edited stays in the row while the window narrows, and on a touch screen (pointer: coarse) the open tab's wider 160 px minimum is counted.

Design follows Firefox's "List all tabs" and VS Code's tab overflow rather than Chrome's tabs shrinking to their icon: an Ovis tab is told apart by its name (DESIGN.md updated).

Screenshots (light, test session, 20 tabs)

Desktop 1280 with the More list open, and a 390 phone (unchanged: the header title lists the tabs). Screenshot files are in the lane report.

Review

  • omo (dori review) at 3184203: CLEAR.
  • Codex (gpt-6.1-terra, xhigh) found 3 MEDIUMs, all reproduced with the pure functions and fixed in 19d7433 with unit tests that fail on the old code: a drop into a gap of hidden tabs was a no-op, a resize could remove an open rename field, and tablet widths counted the open tab at 120 px instead of 160 px.

Validation

  • Failing first: scripts/tab-overflow-regression.ts on unchanged main fails with 20 tabs, the last open: 20 tabs that do not fit show no More button in the header's row. With the change, it passes: no tab under 120 px, no scroll, More counts the hidden tabs, the list shows them in order, picking metrics opens it in the row, and 1024 px keeps the minimum. A close shows only on the open tab and the hovered one. The wheel checks now run on a split half's strip.
  • bun test src/lib/tabOverflow.test.ts src/lib/i18n.test.ts src/components/TabStrip.appLayout.test.tsx src/lib/tabOrder.test.ts: 35 pass.
  • bun run check fast: green at 19d7433 and again after merging main at the head.
  • bun test src/lib/tabOverflow.test.ts src/lib/tabOrder.test.ts: the new cases fail on the previous code (2 fail) and pass now.
  • In the CI runner image (herdr-ci-runner:local, uid 1001): ui-regression, ui-contexts-regression, tab-overflow-regression and the other browser scripts that touch the tab row: ui-regression PASS, ui-contexts-regression PASS (it runs tab-overflow, tab-menu, mobile-tabs, split-view, chat-size), and 12 standalone scripts PASS (agent-lock, herdr-prefix-keys, mirror-fold, palette-machines, pane-lifetime, phone-glass-header, phone-safe-area, phone-split-grid, shortcut-exact-modifiers, sidebar-declutter, workspace-rows, new-session-skills).
  • Runner image at 19d7433: ui-regression PASS (one retry: the first attempt hit follow-focus's split step with a Playwright fulfill: Route is already handled! error, also seen in an earlier run before follow-focus was touched), ui-contexts-regression PASS.
  • Test helpers that assumed every tab is in the row: follow-focus-regression now counts the tabs behind More as listed, and tab-pick.ts gains clickTab, which opens a tab from the More list when the row is full (used by chat-size's attach lifecycle checks).
  • Not run: integration suite (no server/shared change), Windows/macOS jobs.

@coderabbitai

coderabbitai Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 5 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 6dfcc17 and c7f0ef3.

Files selected for processing: 16

  • DESIGN.md
  • changelog.d/header-tab-overflow-more.md
  • scripts/chat-size-regression.ts
  • scripts/follow-focus-regression.ts
  • scripts/tab-overflow-regression.ts
  • scripts/tab-pick.ts
  • src/components/TabStrip.tsx
  • src/lib/i18n/terminal.ja.ts
  • src/lib/i18n/terminal.ko.ts
  • src/lib/i18n/terminal.zh.ts
  • src/lib/tabOrder.test.ts
  • src/lib/tabOrder.ts
  • src/lib/tabOverflow.test.ts
  • src/lib/tabOverflow.ts
  • src/lib/useTabReorder.ts
  • src/styles.css
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@devswha

devswha commented Nov 6, 2026

Copy link
Copy Markdown
Owner Author

Review summary at c7f0ef3:

  • omo (dori review): CLEAR at c7f0ef3.
  • Codex pass 1 (3184203): 3 MEDIUMs, all fixed in 19d7433 with unit tests that fail on the old code (drop into a gap of hidden tabs, rename field removed by a resize, tablet open-tab width).
  • Codex pass 2 (c7f0ef3): the three fixes verified. One remaining MEDIUM, not introduced here and not reproduced in a browser: a rename draft is lost when the window is resized across 769px, because the header strip and the pane's own strip are separate components (App.tsx since the header row landed). Left for a follow-up if it is reproduced.
  • CodeRabbit: review limit reached, no review ran on this PR.
  • Required checks (Fast checks, Integration tests, Native Windows install): pass at c7f0ef3.

@devswha
devswha merged commit 0b8a0a2 into main Nov 6, 2026
23 of 25 checks passed
@devswha

devswha commented Nov 6, 2026

Copy link
Copy Markdown
Owner Author

Merge note (merge pass) at head c7f0ef3:

  • Merged on GitHub's required checks, all green on this head (Fast checks, Integration and browser, Native Windows install).
  • omo review receipt: CLEAR at this exact head. Unresolved review threads: 0 (GraphQL). CodeRabbit: neutral; no CodeRabbit review ran on this head.
  • Owner-approved desktop tab row: tabs at least 120 px, the overflow behind a More list (▾ N) after +, the open tab always in the row, the close X only on the open or hovered full-size tab; phone unchanged. The earlier browser failure (mirror-fold-demo-regression) was main's own red, fixed by test(mirror-fold): wait for the phone header instead of sampling it #3204; this head's checks passed on rerun.

@devswha
devswha deleted the feat/tab-overflow-more branch November 6, 2026 16:40
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