[Bug Fix] Overlays: release Command scroll lock on teardown, settle Tooltip exit on cancel

Merged
DJ
1mo ago
+14-5

Follow-up to #506. That PR moved every overlay's hide behind the exit animation. Two overlays still leak on an interrupted/torn-down close.

CommandDialog — body stays scroll-locked after teardown

show() adds overflow-hidden to <body>; it is removed only in afterExit(). When the dialog is destroyed without a dismiss() (Turbo navigation, turbo:morph on a persisted body), disconnect() → settleExit(panel) sees data-state="open" and returns early, so afterExit() never runs and the page stays unscrollable.

Fix: disconnect() releases the lock unconditionally, independent of exit state.

Tooltip — exit run cut short orphans the cloned node

Tooltip mounts a clone on <body> and removes it on animationend. It never listened for animationcancel, so an exit animation interrupted by a backgrounded tab or a competing style change leaves the clone in the DOM forever. The other overlays already listen for both events; this brings Tooltip in line. The existing animationName === "exit" + data-state === "closed" guards already do the right thing for the cancel case.

How to test

CommandDialog scroll lock

  1. Open a Command dialog (<body> gains overflow-hidden).
  2. Navigate away via a Turbo link (or trigger a morph) while it is open, instead of closing it.
  3. Before: the next page cannot scroll — overflow-hidden is stuck on <body>. After: the page scrolls normally.

Tooltip orphan

  1. Hover a tooltip trigger to show it, then move away to start the exit animation.
  2. Interrupt the exit (switch tabs mid-fade, or remove the trigger).
  3. Before: a stray tooltip node remains under document.body. After: it is removed.

Both are JS-only lifecycle fixes; mcp/data/registry.json is regenerated from the two controllers.


Summary by cubic

Fixes CommandDialog leaving <body> scroll-locked when Turbo navigation or morph tears it down mid-open, and fixes Tooltip leaving a cloned node behind when its exit animation is cancelled.

Bug Fixes

  • CommandDialog releases the overflow-hidden scroll lock on disconnect() only when the panel is still open; the normal close path already releases it in afterExit().
  • Tooltip now listens for animationcancel in addition to animationend, so a cut-short exit removes the cloned node.
  • Both fixes are JS-only; mcp/data/registry.json is regenerated from the two controllers.