Follow-up to #530 (the macOS title-bar hover-tooltip fix).
Right now the bubble anchors to the trigger element's left edge and grows rightward (with a fallback to right-aligned on overflow). That's stable and predictable, but it doesn't match native macOS behaviour, where the tooltip appears near the cursor instead of the control's geometric edge.
Proposed behaviour
Pin-at-show-time (option 1 from the design discussion in T-019e156c-969d-76f9-970e-221951a7fd4c):
- When the show-timer fires (or the hover-handoff fast path triggers), snapshot the current cursor coordinates.
- Position the bubble at
(cursorX + CURSOR_OFFSET_X, cursorY + CURSOR_OFFSET_Y) — roughly +12 / +18 to clear the pointer, matching Cocoa's offsets.
- Once shown, the bubble does NOT follow further pointer moves inside the same trigger. macOS native tooltips behave this way too — they freeze on appearance.
- Right-overflow fallback: if
cursorX + offset + bubbleWidth > parent.right, anchor to the LEFT of the cursor instead (cursorX - offset - bubbleWidth).
Implementation sketch
Renderer (TitleBarApp.vue):
handleTooltipPointer already has event.clientX / clientY — store them in a lastCursor ref updated on every move.
fireShowTooltip reads lastCursor at call time so the snapshot is always the cursor's position when the tooltip actually shows (covers both the 400 ms delayed first-show and the immediate hover-handoff path).
- Bridge payload: replace
leftX / rightX / bottomY with cursorX / cursorY. Keep leftX / rightX only if we still want the trigger rect for the right-overflow fallback (otherwise compute it purely from cursor + parent bounds).
Preload + bridge type (comfyTitleBarPreload.ts): payload shape change.
Main (positionTooltipPopup in src/main/index.ts):
x = cursorX + CURSOR_OFFSET_X - SHADOW_GUTTER by default
- Right-overflow fallback to left-of-cursor
- Drop
TOOLTIP_VERTICAL_GAP / bottomY plumbing — replaced by cursorY + CURSOR_OFFSET_Y
Tests (TitleBarApp.test.ts): signature update + an assertion that the x/y forwarded to the bridge are derived from the synthetic PointerEvent's clientX / clientY.
Why follow-up, not in #530
The trigger-anchored layout is already a clear improvement over the original centered version, and the cursor-anchored variant has its own design questions (offset constants, exact overflow strategy, possible interaction with the hover-handoff window). Worth a separate, focused PR.
References
Follow-up to #530 (the macOS title-bar hover-tooltip fix).
Right now the bubble anchors to the trigger element's left edge and grows rightward (with a fallback to right-aligned on overflow). That's stable and predictable, but it doesn't match native macOS behaviour, where the tooltip appears near the cursor instead of the control's geometric edge.
Proposed behaviour
Pin-at-show-time (option 1 from the design discussion in T-019e156c-969d-76f9-970e-221951a7fd4c):
(cursorX + CURSOR_OFFSET_X, cursorY + CURSOR_OFFSET_Y)— roughly+12 / +18to clear the pointer, matching Cocoa's offsets.cursorX + offset + bubbleWidth > parent.right, anchor to the LEFT of the cursor instead (cursorX - offset - bubbleWidth).Implementation sketch
Renderer (
TitleBarApp.vue):handleTooltipPointeralready hasevent.clientX/clientY— store them in alastCursorref updated on every move.fireShowTooltipreadslastCursorat call time so the snapshot is always the cursor's position when the tooltip actually shows (covers both the 400 ms delayed first-show and the immediate hover-handoff path).leftX/rightX/bottomYwithcursorX/cursorY. KeepleftX/rightXonly if we still want the trigger rect for the right-overflow fallback (otherwise compute it purely from cursor + parent bounds).Preload + bridge type (
comfyTitleBarPreload.ts): payload shape change.Main (
positionTooltipPopupinsrc/main/index.ts):x = cursorX + CURSOR_OFFSET_X - SHADOW_GUTTERby defaultTOOLTIP_VERTICAL_GAP/bottomYplumbing — replaced bycursorY + CURSOR_OFFSET_YTests (
TitleBarApp.test.ts): signature update + an assertion that the x/y forwarded to the bridge are derived from the syntheticPointerEvent'sclientX/clientY.Why follow-up, not in #530
The trigger-anchored layout is already a clear improvement over the original centered version, and the cursor-anchored variant has its own design questions (offset constants, exact overflow strategy, possible interaction with the hover-handoff window). Worth a separate, focused PR.
References