fix(cmux-next): keep sidebar close and hover state local

Merged
TE
19d ago
+127-28

Problem

Closing the last/bottom workspace can select the top row, and a workspace removed under a stationary pointer can retain hover controls while its row is animating away. Sidebar hover entry also feels delayed by an unnecessary fade.

Change

  • resolve optimistic sidebar closes with the existing browser-style successor rule: next surviving row, then previous
  • preserve the pre-close workspace order in the instant-close repair path
  • clear hover state before removed/recycled rows leave the realized list
  • reveal workspace hover controls immediately and use the default instant hover-out token for fills
  • add close-selection and stale-hover regressions

Validation

  • swiftc -parse on every changed Swift source/test file
  • git diff --check
  • native build/runtime validation remains for the managed fleet; no local native build was run

Prior work audited: #21334 sidebar motion hardening, #21395 keyboard-only focus treatment, #21459 tab-group successor focus.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Fixes sidebar close and hover handling so closing a workspace picks the right successor and rows removed under the pointer don't keep stale hover state.

Closing the last workspace could fall back to the first surviving row. The close path now preserves the pre-close workspace order and picks the next surviving row, then the previous, as the new active workspace. Hover state is cleared before a row leaves the realized list, so a row removed under the pointer doesn't carry its hover fill or controls through the close/recycle animation. Hover controls reveal immediately on pointer entry; only clearing them keeps the short hover-out transition.

Tests

  • Adds close-selection regressions covering middle, last, multi-close, and unfocused closes.
  • Extends hover motion tests for immediate entry and stale-hover cleanup on row removal.