cmux NEXT sidebar: hover hides the trailing spinner; inner tab dots on the trailing column

Merged
TE
9d ago
+353-89

Leo 2026-10-28: "Honestly, dude, if you're hovering over a thing, you— holy fuck. If you're hovering over a workspace or whatever, just don't show the spinner. Also, wow, do we seriously not have these fucking things aligned? Like, why the fuck is it not aligned? Oh, because it's the inner tab thing, huh?"

What changes

  • Inner tab rows: a listed tab's unread dot centers on the trailing column every other dot, spinner and chevron shares (it sat 2 pt right of it). A tab's status keeps the column; a dot beside a status sits left of it.
  • Hover hides the mark: a hovered workspace row draws no dot or spinner while its close, more or pin show, under every sidebar.rowCloseSpot; at the default end spot the end-most control takes the column (a row that cannot close puts ⋮ there).
  • Group headers: a hovered loading header hides its spinner at once and shows its chevron on the column, with + and ⋮ left of it (the spinner no longer slides beside them).
  • Hover-out: the controls clear at once while the mark comes back, so no frame draws both (Codex review).
  • Colours, glass, densities and defaults unchanged. plans/cmux-next/sidebar-owner.md updated (takes back 10990df76a7's "a hover no longer hides the mark" and the 10-20 sliding header spinner).

Before / after

Fixture SidebarTrailingColumnGalleryTests (GUI, fleet): every row kind, groups at depth 0 to 2, inner tabs at depth 0 and 2. Comfortable, 300 pt. Rendered at 66f9626c; later commits change only the hover-out fade timing, not these still states.

Before (base eae25617)After
At rest (zsh, claude: inner tab dots)before restafter rest
"subrouter 2" hoveredbefore hover rowafter hover row
"Folded loading" hoveredbefore hover headerafter hover header

Capture tour-core at 1a0c74cefd7b (fleet build, capture mini, text checked for private data)

LightDark
lightdark

Measured (list x, 300 pt, from geometry.json)

compact columnoff-column markshovered row markshovered loading header
Before (base + tests only)279tab unread dots at 281 (+2.0), both depthsdot + spinner drawn beside the controls (hover test)spinner at 241 and chevron at 279
After279none (all |dx| ≤ 0.5, all |dy| = 0)none (only close / disclosure)chevron at 279 only

Comfortable: column 275; before the tab dots sat at 277 and the hovered header's spinner at 235; after, none off.

Tests

  • SidebarTrailingColumnTests: inner tab rows at depth 0 and 2 on the column and on their row's center line; hoverControlsTakeTheMarksPlace (3 densities × end / middle / even); leavingClearsTheControlsBeforeTheMarkReturns (motion on, corner and trailing badge styles).
  • GroupHeaderTrailingTests, SidebarTabGroupControlsTests: the hover behaviour above replaces the old "spinner slides beside the buttons" and "middle spot keeps the mark".
  • SidebarTrailingColumnGalleryTests writes sidebar-trailing-column-gallery.tar: PNGs plus geometry.json (per row: native accessibility identifier, kind, parent, depth, hovered; each drawn mark's center and each shown control's frame, as view frames in list points, top-left origin; not AX).
  • Fleet at head 1a0c74ce (rebased onto feat-cmux-next, with 1daea603): all 10 suites pass (SidebarTrailingColumnTests, GroupHeaderTrailingTests, SidebarTabGroupControlsTests, GroupHeaderHoverRevealTests, SidebarTabLineTests, SidebarLookContractTests, SidebarIconMeaningTests, SidebarRowCornerBadgeTests, SidebarStatusGlyphCenterTests, SidebarRowGutterTests). SidebarNestedGroupAlignmentTests.aSubgroupSitsInsideItsParentsRail and SidebarGroupRailAlignmentTests.sixLevelsEachDrawAtTheirOwnX fail the same way on base eae25617.

Review

Codex gpt-6-astra (high, fast): round 1 BLOCK (hover-out cross-fade on rows and headers; fixed; a third finding, hiding a tab row's status on bare hover, declined: tab rows have no hover controls to take its place), round 2 BLOCK (the trailing badge style's unread count; fixed), round 3 SHIP at b84c2355; the head adds only a test-only @MainActor on a helper.

Risk

Low to medium: hover visibility and one dot's x in sidebar rows; no model change. A hovered workspace row no longer shows its status mark (Leo's ask).

Agent session: agent session

🤖 Generated with Claude Code