Conversation
) Two directions from Discussion #426, each a per-device setting and the new default. Tab Grouping (tabGrouping: 'state' | 'none', default 'state', option C): tabs are grouped needs you (red, plus failed sessions), waiting (yellow), working and idle (also ended, exited panes and web tabs), most urgent on top. The desktop header strip draws a row per group with its label and count in a left gutter; the flat vertical rail and the sidebar draw a section per group; tablets keep their scrolling row with inline dividers; phones keep the chip row in group order without headings. Classification is the home screens' own (_mobileOverviewState/_mobileOverviewExit), the fold into four groups is pure in CodemanTabTriage (constants.js). It is flex `order` plus aria-hidden heading/break elements reconciled in place after both render paths, never a DOM reorder, so Alt+N, the keyboard walk and drag keep reading tab order; a drop is refused across groups. Named groups in the vertical rail take precedence. Header Stats Style (headerStatsStyle: 'classic' | 'compact' | 'tiles', default 'tiles', option G): tiles give WS, CPU, MEM and each plan window a label-over-value tile with a bar underneath; compact is one WS/CPU/MEM pill with sparklines plus a plan-ring pill; classic is the header as before. Desktop only (classic below 768px and in solo windows). The clustered styles move #connectionIndicator into #headerSystemStats and #planUsageChip after it, and classic moves them back to comment anchors; WS stays out of a hidden System Stats pill. The extra parts are always rendered and hidden by default in CSS, so classic is unchanged. Tests: test/tab-triage.test.ts, test/header-stats-style.test.ts; three source pins in test/tab-rail-order.test.ts follow renamed lines. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This builds two of the directions from the tab strip discussion (#426): C · Triage for the tabs and G · the right side of the header. Each lands as a setting next to the existing tab and header options, and each one is the new default.
Tab Grouping, new default "By state". Tabs are grouped by what each session needs from you, most urgent on top:
On desktop the header strip becomes one row per group, with the group name and count on the left. The vertical rail and the left sidebar show the same groups as sections. Empty groups are not drawn. App Settings → Appearance → Tabs → Tab Grouping → None brings back the single list in tab order.
Header Stats Style, new default "Tiles". App Settings → Header & Panels → Header Stats Style picks how the WS readout, CPU, MEM and the plan usage windows are drawn. These are the three variants from the G mockup:
There are no server behaviour changes. The settings schema gains two optional enum keys (
tabGrouping,headerStatsStyle), and both are per-device display keys like the other tab options, so a phone and a desktop can differ. Because both are new defaults, every desktop picks them up on its next load; None and As before are the way back.How the grouping works
_mobileOverviewState()and_mobileOverviewExit(), the classifier the phone overview, the desktop home rail and the activity-sorted rail already use, so the strip cannot disagree with them about who is waiting. The fold from six states into four groups is pure and lives inCodemanTabTriage(constants.js).orderproperty plus one heading and one row break per group (aria-hidden, so the tablist still holds only tabs).#sessionTabsstays in tab order, so theAlt+1..9numbers never change, the arrow-key walk follows what you see, and drag still works. A drop is only accepted inside the same group; across groups the tab would stay in its own group anyway and land somewhere you did not put it.orderand the heading counts move. Headings are reconciled in place, so an SSE tick that changes nothing writes nothing.How the header styles work
data-header-statson<html>drives every rule. It is stamped by the pre-paint script and then byapplyHeaderStatsStyle()on load and on save. Below 768px and in a detached solo window it is alwaysclassic; the stats are hidden there anyway.#connectionIndicatorinto#headerSystemStatsand#planUsageChipright after it. Switching back to As before returns both to comment anchors left at their template positions. Ids are unchanged, so every writer still finds them. The WS readout only joins the pill while System Stats is shown, so hiding System Stats never hides WS.test/connection-indicator.test.tspins the descriptor's exact shape.Testing
npm test(the CI gate): 458 files and 8899 tests pass (12 skipped).typecheck,lint,format:check,check:public-assets,check:frontend-syntax,check:browser-excludesandcheck:lockfilepass, and both stylesheets parse with PostCSS.test/tab-triage.test.ts(23 tests: the pure layout, plus the shippingapp.jsandmobile-overview.jsin JSDOM, covering incremental moves, heading reconciliation, exited and failed sessions,noneleaving no trace, the sorted rail, named groups winning, the drag guard, and a stalemobile-overview.jsdegrading to the flat strip) andtest/header-stats-style.test.ts(13 tests: run on the real<header>fromindex.html, covering the moves, the round trip back to the template order, WS with System Stats hidden, rings and meters, tile words and sparklines).test/tab-rail-order.test.tsthat matched source lines I renamed (railSortOrderis now fed throughlistOrder). The behaviour they guard is unchanged.origin/masterworktree:tab-activation,session-sidebar-ux,tab-rail-resizeandinline-renameshow the same single failure as master (the rail rename clamp test that fix(tabs): grouped rail interaction fixes for inline rename #526 addresses).test/mobile/tabs.test.tsmatches master (one failure there too, in keyboard focus). One swipe test failed once on the branch and passed on two reruns.CODEMAN_INSTANCE) with Playwright at 1440, 700 and 390px wide, dark and light skins: a permission prompt sent through the real hook route moved a tab into Needs you over SSE and back out onstop. Changing both settings in the App Settings modal applied them without a reload and persisted them.Reviewing the diff
About 1,540 added lines, but most of them are not logic:
styles.css+370: two self-contained blocks appended at the end of the file (tab grouping, then header stats styles). No existing rule is edited.docs/wiki/The-Dashboard.md,docs/wiki/Settings-Reference.md, two sections indocs/architecture-invariants.mdand two entries inCLAUDE.md.constants.js(the pure grouping helper, mostly comments),app.js(the gate, the per-pass layout, heading reconciliation, the drag guard, plan rings and meters, WS tile words),settings-ui.js(load, save, apply) andpanels-ui.js(sparkline history).Not in this PR
The screenshots use invented session names.