fix(ui): a caption never opens under a finger

On an iPad a tap's synthetic mouseenter opened the Tooltip; WebKit then took the
tap as a hover and swallowed its click, so every rail button needed two taps,
and with no mouseleave from a finger the caption stayed up. Tooltip now opens
for a mouse and a key's focus only (owner: no captions on touch).
This commit is contained in:
2026-10-08 02:45:48 +02:00
parent c9b8fe15a3
commit c3664826fe
4 changed files with 47 additions and 1 deletions
@@ -62,6 +62,11 @@ export interface AnchoredPopoverOptions {
* preview (ui/MediaPreview): a keyboard walk down a grid would otherwise pop a panel at every stop,
* and a tap is the card's play. */
pointerOnly?: boolean;
/** Hover mode only: never opened by a finger, still by a mouse and a key's focus. A caption over a
* control (ui/Tooltip): on an iPad the tap's synthetic mouseenter showed it, WebKit then took that
* first tap as a hover and swallowed its click (every rail button needed two taps), and with no
* mouseleave from a finger the caption stayed up. */
mouseHoverOnly?: boolean;
/** Index of the item that is currently CHOSEN, for a single-choice menu/listbox. Opening then
* lands the roving focus on it instead of the first item — the behaviour a "pick one of these
* modes" menu needs. Leave unset for action menus and multi-select toggle lists. */
@@ -166,7 +171,7 @@ export function useAnchoredPopover(opts: AnchoredPopoverOptions) {
move: false,
// A hover-card is a pointer affordance either way; a hover-ALSO menu must ignore touch, or the
// synthetic mouseenter a tap emits would race the click toggle (open, then immediately shut).
mouseOnly: !isHover || !!opts.pointerOnly,
mouseOnly: !isHover || !!opts.pointerOnly || !!opts.mouseHoverOnly,
// A submenu wants a shorter intent delay than a hover card: the pointer is already inside a
// menu, so the "did they mean it" question is mostly answered.
delay: opts.hoverDelay ?? (isHover ? { open: 120, close: 140 } : { open: 90, close: 120 }),