mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-05 15:09:42 +02:00
ffaa5ee80c583b8e2983e773c0f1e0924bebaf34
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7917273188 |
fix(tabs): collapsed-header alerts, quieter layout reads, tree key and touch fixes (#517, #519 review)
Maintainer merge-time fixes for the grouped vertical rail (#517) and its tree semantics (#519), from the two PR reviews. #517 minors - A collapsed group hid rows that need the user with no signal on its header. The header now takes the most urgent alert among the session rows its collapse hides, in the tab alert language (tab-alert-action red ring, tab-alert-idle yellow ring, the existing ::before rules extended to the header). New pure hiddenGroupAlerts() over a per-section `hidden` list; _syncTabGroupHeaderAlerts() patches it on BOTH render paths, since alerts change without a rebuild. The kept selection draws its own ring and is not counted. - Every layout read rebuilt the whole tab strip, and failed reads retried every 5 s forever. _applyTabLayout() now rebuilds only when the structure key changed. The key drops the layout version (bumped on every session create/close and order PUT) and instead carries group names and the rows each collapse hides, so a version bump that moves nothing costs nothing and a rename still rebuilds. The load coordinator backs off (5, 10, 20, 40 s, capped at 60 s) and stops after 4 retries; the next SSE init or tab:layoutChanged tries again, a success resets. - A malformed stored collapse value disabled collapse on that device for good. A parse or shape error now reads as nothing collapsed and is rewritten to []; ok:false stays reserved for a store that throws. - Ctrl+Shift+{ / } still reordered across groups, where the server re-ranks per group, sends no session:orderChanged and leaves this client's sessionOrder and Alt+N targets diverged. The move is now a no-op unless the neighbour is in the active session's own section (_canSwapActiveTabWith, reading the projection's new sectionByRef, which also covers rows a collapse hides). Within a group the swap still works and the server agrees with it; the flat rail and the strip are unchanged. #517 nits - Keyboard group toggle dropping focus: already fixed by #519's focus-by-identity; the Enter toggle test now pins focus on the header. - Header <button> inside role=tablist: moot, #519 made the header a treeitem inside role=tree. - Byte-identity test not comparing against master: skipped in the suite (a test cannot read another revision's files portably). Checked by hand instead: the flat strip and flat rail markup of this branch before and after this commit are identical in all 16 cases (both orientations, manual and activity sort, no layout and zero groups, full and incremental paths). - Doubled blank line in docs/architecture-invariants.md: removed. #519 minors - A tap on a tree header or unselected row dismissed the touch keyboard: the roving tabindex parks those at -1, so the [tabindex] arm of MOBILE_KEYBOARD_DISMISS_EXEMPT_SELECTOR missed them. The selector now lists [role="treeitem"]. - The tree key handler acted on keys pressed on a focused control inside a row (Enter on the overflow button re-selected and reloaded the active session instead of reopening its menu). It now returns unless the key landed on the treeitem itself. #519 nits - aria-posinset/setsize went stale when the activity-sorted grouped rail re-sorted rows on the incremental path. The position pass is extracted (_applyTabTreePositions) and re-run, with aria-selected and the header alerts, at the end of the incremental branch while the rail is a tree. - An expanded group with no open rows was announced as an expanded parent owning an empty group. A group with no open rows is now a tree leaf: no aria-expanded, no aria-owns, its rows container presentation; Left and Right do nothing on it, and its chevron keys off the section's collapsed class instead of aria-expanded. Tests: tab-layout-browser (malformed storage, backoff with a bounded drain, structure key, hidden alerts, leaf groups, sectionByRef), tab-layout-rail (header alerts on both paths, render-on-change, backoff without rebuilds, malformed storage, Ctrl+Shift section gate, in-row control keys, leaf header keys, posinset after an incremental re-sort, the dismiss selector matching tree items), and three new Chromium tests in tab-activation.browser (Enter on a focused overflow button, the touch keyboard staying up on tree taps, the collapsed header's red ring). Every new test fails on the pre-fix sources. Docs: architecture-invariants owner-tab-layouts and keyboard-dismissal sections, one clause in CLAUDE.md's dismissal rule. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
98c6c1881d |
feat(tabs): full-row activation and tree semantics for the grouped rail
The grouped vertical rail is now an ARIA tree with a tree keyboard model, and tab rows are pinned as full-row activation targets whose controls keep their own actions and stable hit targets. Tree semantics (grouped vertical rail only): - #sessionTabs becomes role=tree while grouped and returns to its shipped role=tablist and label when grouping ends. The header strip, sidebar and flat rail keep role=tablist / role=tab exactly as before (the flat rail's markup is unchanged byte for byte). - A named group's header is a level-1 treeitem with aria-expanded that aria-owns its rows' role=group (rows are level 2). Ungrouped rows and the row a collapsed group keeps showing are level-1 items; a collapsed header owns nothing, and the "Ungrouped" heading is a visual divider hidden from assistive tech. aria-level, aria-setsize and aria-posinset are set on every item, and aria-selected follows the selection without a rebuild. - Exactly one treeitem carries tabindex=0 (roving). Controls inside rows leave the tab order, so Shift+F10 / ContextMenu open a row's actions (session action menu, web tab settings). - Up/Down walk visible items, Home/End jump, Right expands a header or enters it, Left collapses a header or climbs from a row to its header, Enter/Space select a row or toggle a header. With the activity sort on, the walk follows painted order within each group; the flat list keeps its whole-list walk. - Focus survives a full re-render by identity (a row a collapse just hid hands focus to its header), but a render never pulls focus into the rail. - The group header is the treeitem itself (no nested button), still toggled by click through the same onclick and still the lineage proxy anchor. Full-row activation: - Clicking a row's status dot, mode chip, name or padding already selected it upstream; that is now pinned in real Chromium for the strip, the flat rail and the grouped rail, together with every control (gear, detach, close, overflow, web tab gear and close) running only its own action. - The close control now shows a pointer like its siblings instead of the default arrow. - Enter/Space on a focused web tab in the flat list opens it; it used to call selectSession(undefined). - The action controls are pinned to stay under the pointer when a row is hovered (no reflow-on-hover moving the gear out from under a click). New Chromium suite test/tab-activation.browser.test.ts is listed in BROWSER_TEST_GLOBS (run with npm run test:browser). |
||
|
|
7cbce5bf6c |
feat(tabs): grouped vertical rail from owner tab layouts
The vertical tab rail now reads the owner's tab layout (GET /api/tab-layout) and draws its groups as collapsible sections. This is the first frontend consumer of the tab-layout backend and it is read-only: nothing in the browser writes the layout yet. - tab-layout-browser.js (new, pure, loaded before app.js): projects the layout onto the live sessions and open web tabs, renders the grouped markup, stores collapse per device, and sequences loads newest-wins with a bounded retry on failure. - app.js: loads the layout on init and on tab:layoutChanged, renders the grouped rail from the same per-row markup the flat rail uses, falls through to a full render whenever the grouping structure changes, and withholds drag-reorder in the grouped rail. - Grouping is opt-in by construction. With no layout, a failed read, a layout without groups, or a horizontal strip, the rail renders exactly as before (byte-identical markup). - Grouping is a render layer only: sessionOrder, Alt+N, Ctrl+Tab and the palette keep reading the server-projected order, and row badges keep their Alt+N slot. - A collapsed group still shows the active row; lineage arcs to a hidden session anchor to its group header. - webview-tabs.js: renderWebviewTab() extracted so a single web tab can be placed into its group with unchanged markup. |