feat(HoverCard): add enableTouch prop for touch devices#2687
Conversation
HoverCard ignores touch input by design (Radix parity), so it can't be opened on mobile. Add an opt-in `enableTouch` prop that lets a tap toggle the card open/closed, gated to `pointerType === 'touch'` so hover/mouse behavior is unchanged. Toggle runs on `pointerup` so a scroll gesture (which fires `pointercancel`) won't trigger it. Also clear the pending open timer in `handleDismiss` so a dismiss can't be reopened by a lingering focus/hover open timer. Resolves unovue#1969
📝 WalkthroughWalkthroughThis PR adds touch pointer support to the HoverCard component via a new ChangesHoverCard touch support
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
commit: |
🔗 Linked issue
Resolves #1969 (also covers nuxt/ui#2346)
❓ Type of change
📚 Description
HoverCardignores touch input by design (ported from Radix), so it can't be opened on mobile. The trigger only reacts to real pointer hover (pointerenter/pointerleave, both wrapped inexcludeTouch) andfocus, neither of which reliably fires on a tap.This adds an opt-in
enableTouchprop onHoverCardRoot(defaults tofalse, so existing/Radix behavior is unchanged). When enabled, tapping the trigger toggles the card open/closed:pointerupand gated topointerType === 'touch', so mouse/hover behavior is untouched and a scroll gesture (which firespointercancel, notpointerup) won't accidentally open it.onOpenChange(true)/ closes viaonDismiss().DismissableLayerdefers its own dismiss to theclickevent on touch, which runs after ourpointerupand resolves idempotently (no close-then-reopen race).It's kept opt-in rather than always-on because always enabling it would override HoverCard's intentional "supplemental, non-interactive, not-for-touch" semantics and would conflict when the trigger is a real link (tap would both navigate and toggle).
Also includes a small correctness fix:
handleDismissnow clears the pending open timer, so a dismiss can't be reopened by a lingering focus/hover open timer (a latent bug on desktop too).📝 Checklist
Summary by CodeRabbit
New Features
enableTouchprop. When enabled, touch taps on the trigger toggle the card open/closed (disabled by default).Documentation
enableTouchprop and its behavior.