From d3fc07ee2800410ad6d73b28bfb37572605980b4 Mon Sep 17 00:00:00 2001 From: Aamer Akhter Date: Fri, 9 Oct 2026 21:30:49 -0400 Subject: [PATCH] feat(tabs): keep alerted tabs visible during a rail search A session with a tab alert (red action or yellow idle, whatever tabAlerts holds, the same set a collapsed group header surfaces) now stays visible while the rail search or the sidebar filter is narrowing the list, even when its name does not match. A prompt waiting on you should never be hidden by a view filter. The pure CodemanTabSearch.filter decides it: a row passed with keep: true is never hidden. It counts toward its group, so the group stays on screen and the header number is the rows left showing, but not toward matchCount, so "No sessions match" still shows above a lone alerted row. _applyTabListFilter() flags session rows from tabAlerts; web tabs carry no alerts and are never kept. No new wiring: updateTabAlertFromHooks() and _onSessionWorking() already call renderSessionTabs(), and both render paths end in the shared filter. --- CLAUDE.md | 2 +- docs/wiki/The-Dashboard.md | 2 +- src/web/public/app.js | 14 ++++-- src/web/public/constants.js | 19 +++++--- test/tab-rail-search.test.ts | 92 +++++++++++++++++++++++++++++++++++- 5 files changed, 117 insertions(+), 12 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 182c84eb..9e3eea52 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 `