- Shipped
- September 5, 2026 at 10:22 PM UTC
- Author
- Kamo
- Commit
- d4d2c84
The previous attempt at this fixed the wrong handler. It taught the reconcile in useNavHoverPeek to see through the bar, which was worth doing and was not what was collapsing the rail: NavPri also has its own onPointerLeave on the <nav>, and that fires setPeeking(false) directly, before the reconcile gets a say. The bar is rendered from a portal at <body>, so crossing onto it IS a real boundary crossing and the browser delivers a real leave for it. handlePeekLeave now resolves event.relatedTarget — where the pointer went — through a registry the overlay writes to as it mounts, so a bar resolves to the element it scrolls. Moving onto the rail's own scrollbar is therefore not leaving the rail; another panel's bar, or a dialog, still is, and there is a test for each of those. A registry rather than a DOM or geometric answer, because neither is available: the bar is not a descendant of what it scrolls, and a pointerleave handler is handed the element the pointer went TO and nothing else. Measured in a real browser with a real pointer, driving the same rail before and after — resting on the bar's track: before rail widths [192, 87, 80], 2 changes, ends collapsed after rail widths [260], 0 changes, ends peeked and dragging the thumb now holds [260] throughout while the list scrolls 0 -> 550, with jump-to-end taking it to 1036. Also corrects a comment written on a wrong reading: an earlier dump suggested Chrome excludes the gutter from hit-testing and the rail was not under the bar at all. It was taken after the collapse had begun. Probing while the rail is still open gives [OVERLAY, OVERLAY, IN RAIL, IN RAIL, IN RAIL] — the rail is there; it was never the problem.