From 7c3877016b61ac85d19de05a1632fcdb78199aba Mon Sep 17 00:00:00 2001 From: Aamer Akhter Date: Fri, 9 Oct 2026 20:55:32 -0400 Subject: [PATCH] feat(tabs): search sessions by name on the vertical rail A "Search sessions" box at the top of the vertical tab rail narrows the list to the tabs whose name matches (case-insensitive substring; a web tab matches by its title). It searches every group, collapsed ones included: while a search runs the projection draws every group open and the header will not toggle, and the stored per-device collapse state is left alone. Groups with no match hide, an empty result says "No sessions match", and the flat rail (no groups) filters the same way. Escape or the clear button empties it; leaving the vertical orientation resets it. It is a view filter only: rows get the same tab-filtered-out class the sidebar filter box uses, through one shared _applyTabListFilter() over the pure CodemanTabSearch matcher in constants.js. Grouping, order, Alt+N badges and drag are untouched, nothing is persisted or sent to the server. The sidebar keeps matching name plus working directory. In the grouped tree, hidden rows and the headers of emptied groups leave the roving walk and posinset/setsize, and the tab stop moves onto a visible item. zh-CN strings added. --- CLAUDE.md | 2 +- config/test-suites.ts | 1 + docs/wiki/The-Dashboard.md | 2 +- src/web/public/app.js | 128 ++++++- src/web/public/constants.js | 45 +++ src/web/public/i18n.js | 2 + src/web/public/index.html | 13 + src/web/public/settings-ui.js | 4 + src/web/public/styles.css | 68 ++++ test/tab-rail-search.browser.test.ts | 227 +++++++++++++ test/tab-rail-search.test.ts | 485 +++++++++++++++++++++++++++ 11 files changed, 964 insertions(+), 13 deletions(-) create mode 100644 test/tab-rail-search.browser.test.ts create mode 100644 test/tab-rail-search.test.ts diff --git a/CLAUDE.md b/CLAUDE.md index d122f877..182c84eb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -333,7 +333,7 @@ Frontend JS modules have `@fileoverview` with `@dependency`/`@loadorder` tags. L **Mobile tab strip scrolling** (issue #257): under 768px the tab strip scrolls horizontally, so the active tab must be kept reachable. `_updateActiveTabImmediate()` reveals it via `computeTabScrollLeft()` (constants.js, rect math on the strip's own `scrollLeft`, never `scrollIntoView()`, which scrolls the document under the fixed header); `_fullRenderSessionTabs()` must restore `scrollLeft` across rebuilds and re-reveal only when the active tab changed (`_lastRenderedActiveTabId`) or, grouped by state, the ACTIVE tab moved to another state band (`_noteActiveTabBand()`, both render paths, scrolling row only; another tab's move never scrolls). ⚠️ The phone-block `min-width` on `.session-tab.active .tab-name` keeps the tab's centre off the gear/close icons, sized for numberless tabs 10+ (floor 40px); do not shrink it. ⚠️ Never reintroduce hoisting the active session to the front of the strip. Tests: `test/mobile-tab-tap-zones.test.ts`, `test/tab-triage.test.ts`. → [architecture-invariants#mobile-tab-strip-scrolling](docs/architecture-invariants.md#mobile-tab-strip-scrolling) -**Session list layout: header strip or left sidebar** (`sessionListLayout`, default `header`; per-device via `displayKeys`, also in `SettingsUpdateSchema`): the list can move into a collapsible `