mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-13 17:26:22 +00:00
## Summary
Replace `useMouseInElement` in `CompareSliderThumbnail` with a local
`@mousemove` handler to eliminate ~1s of forced layout per keystroke in
the templates dialog search.
## Changes
- **What**: Profiling the templates dialog search (4× CPU throttle,
cloud distribution) showed a single `getClientRects` block at 977ms
inside Vue's `flushPostFlushCbs → update` path on every keystroke. The
call traces back to VueUse's `useMouseInElement`, which (a) shares a
global `mousemove` listener via `useMouse`, and (b) runs
`el.getBoundingClientRect()` inside a `watch([targetRef, x, y], …, {
immediate: true })`. Every template card with `thumbnailVariant ===
'compareSlider'` mounts one instance — when search filters change and
the page's compareSlider cards re-mount, each instance's `immediate`
watch fires a rect read against freshly-inserted DOM, forcing
synchronous layout of the entire new subtree. With many cards on screen
the costs stack into the ~977ms block. Replaced with a native
`@mousemove` listener bound directly to the slider container; the rect
is read from `event.currentTarget` only when the mouse is actually over
that one card, so the work no longer scales with mounted instance count
and is gated by real pointer activity.
- **Breaking**: None
- **Dependencies**: None
## Review Focus
- UX is unchanged: `sliderPosition` still follows the mouse during hover
and keeps its last value on mouseleave (matches previous behaviour where
`if (!isHovered) return` simply stopped updates without resetting).
- The same `useMouseInElement` pattern still exists in
`src/platform/workflow/sharing/composables/useSliderFromMouse.ts` (used
by `ComfyHubThumbnailStep` in the publish dialog). That path is
single-instance and off the templates hot path, so it's left untouched
to keep this PR scoped — happy to fix it in a follow-up.
- New tests use `userEvent.pointer({ coords })` with a stubbed
`getBoundingClientRect` to lock in the native mousemove path and the
zero-width guard.
## E2E coverage
No `browser_tests/` changes. The `fix:` commit is a defensive clamp
inside `updateSliderPosition`; the overshoot it guards against comes
from subpixel rounding and stale rects observed during hover-in, neither
of which can be deterministically reproduced under Playwright. The perf
change itself is verified via the DevTools profiler (forced-layout block
disappears) — also not assertable as a stable e2e signal across CI
hardware. Both the mousemove-driven slider behavior and the clamp guard
are covered by unit tests in
`src/components/templates/thumbnails/CompareSliderThumbnail.test.ts` (8
cases, including out-of-range pointer coordinates and zero-width
containers).