Replace the all-or-nothing hover freeze in the composer activity bar with
a guard that only pins pill widths when a resize would actually move the
open hover card.
- BotActivityBar.tsx: drop the blanket pinWidth/freezeLayout tied to bar
hover; compute activeCardIndex (pill anchoring the open card) and pin
width / freeze slot layout only for pills at or left of that index.
The card renders side="top" align="start" — anchored to its pill's
left edge — so only those pills can displace it by resizing
- Pills right of the anchor, and every pill when no card is open (even
with the bar hovered), now resize freely with their label swaps and
keep slot layout animation so neighbors ease instead of snapping
- Keep the membership/order freeze on bar hover unchanged — a pill
exiting mid-hover would slide the strip under the cursor, which is
independent of card placement
- Expose the membership hold via a data-hold attribute on the strip
root, since the inline width pin is no longer a proxy for it
- channels.spec.ts: bar-hover test now waits on data-hold, asserts pills
are NOT width-pinned during bar-only hover, and parks the cursor past
the last pill (label swaps can legitimately grow a pill into the
inter-pill gap); add "open card pins only its anchor pill and the
pills left of it" covering both directions; add
waitForSettledPillBoxes helper because pills mount with short generic
labels and grow via the slot layout spring when seeded headlines land
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>