diff --git a/config/test-suites.ts b/config/test-suites.ts index c403421d..ae974542 100644 --- a/config/test-suites.ts +++ b/config/test-suites.ts @@ -28,6 +28,7 @@ export const BROWSER_TEST_GLOBS = [ 'test/tab-focus.browser.test.ts', 'test/session-sidebar-ux.browser.test.ts', 'test/header-divider.browser.test.ts', + 'test/tab-strip-corner.browser.test.ts', 'test/header-host-sensors.browser.test.ts', 'test/session-options-responsive.browser.test.ts', 'test/inline-rename.test.ts', diff --git a/docs/architecture-invariants.md b/docs/architecture-invariants.md index 74497c44..ebba7973 100644 --- a/docs/architecture-invariants.md +++ b/docs/architecture-invariants.md @@ -1047,6 +1047,8 @@ Tests: `test/terminal-touch-tap.test.ts`, `test/session-swipe-gesture.test.ts` ( **Ledger.** CSS only, on `.tabs-ledger` inside `@media (min-width: 768px)` and the header host: the flat list on an auto-fill column grid with equal cells, mono type and a 3px status bar (`--ledger-bar`: yellow for a waiting alert, red for an action alert or an error, muted for stopped, exited and web tabs) instead of the dot. ⚠️ It must not change the markup (pinned: the ledger's innerHTML equals classic's); the rail, the sidebar and narrower strips show the plain list. +**Classic, wrapped: the L-shaped strip.** Once a classic desktop strip in the header host wraps (`tabs-auto-wrap`, or the manual `tabs-two-rows`), `_syncTabStripCorner()` (app.js) adds `.tabs-corner`: `#headerRight` goes `position: absolute` over the strip's top-right corner and the strip runs the header's full width, so only the row(s) beside the toolbar stop short of it and every later row uses the width under it. A flex line cannot be shortened on its own, so in that state the strip is `display: block` with `inline-flex` tabs flowing around a `::before` float sized from the toolbar's box (`--tab-corner-width` / `--tab-corner-height`); the old `row-gap` (lineage's `--lineage-row-gap` included) becomes the tabs' bottom margin and the bottom padding shrinks by the same amount, so row spacing and lineage routing room are unchanged. ⚠️ `updateTabOverflowMode()` removes `.tabs-corner` BEFORE it measures the wrap (the corner takes the toolbar out of the header's flow, which widens the strip), so the wrap is still judged against the one-row layout and an unwrapped strip looks exactly as before. ⚠️ Flex-only rules do not apply to the strip in that state. ⚠️ A strip that already scrolls (past `--tab-strip-max-height`) keeps the plain wrap, checked on the plain strip before the class goes on: the float scrolls with the tabs while the toolbar stays put, and toggling the class on a scrolled strip lets scroll anchoring move it; a strip pushed past the max-height by the float itself falls back too. A first tab too wide for the room beside the toolbar also falls back (the whole first line would drop below the toolbar). A `ResizeObserver` on the toolbar re-decides wrap and corner and redraws the connection lines when a reading or the header divider resizes it without a tab render. Scope: classic arrangement, desktop, header host only; state/case/ledger, the sidebar and the vertical rail never get the class (`applySessionListLayout()` drops it when the strip moves). Tests: `test/tab-strip-corner.browser.test.ts` (browser suite). + With `classic` nothing is left behind: no headings, no breaks, no inline order, no boxes, no name split, no arrangement class. A stale cached mobile-overview.js degrades every grouping to the flat strip. Tests: `test/tab-triage.test.ts`, `test/tab-clusters.test.ts`. ### Header stats styles diff --git a/src/web/CLAUDE.md b/src/web/CLAUDE.md index b6aae1eb..c04ac9c4 100644 --- a/src/web/CLAUDE.md +++ b/src/web/CLAUDE.md @@ -38,7 +38,7 @@ Frontend JS modules have `@fileoverview` with `@dependency`/`@loadorder` tags. L **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 `