@@ -47,6 +47,52 @@ function handlePointerOpen(event: PointerEvent) {
4747 y: Math .round (event .pageY ),
4848 }
4949}
50+
51+ function isPlainLeftClick(event : MouseEvent ) {
52+ return event .button === 0 && event .ctrlKey === false
53+ }
54+
55+ // Tracks direct mouse presses handled in `pointerdown` so the Safari label
56+ // `click` workaround below does not re-focus the trigger after opening.
57+ let openedFromPointerDown = false
58+
59+ function onTriggerPointerDown(event : PointerEvent ) {
60+ // Prevent opening on touch down.
61+ // https://github.com/unovue/reka-ui/issues/804
62+ if (event .pointerType === ' touch' )
63+ return event .preventDefault ()
64+
65+ // prevent implicit pointer capture
66+ // https://www.w3.org/TR/pointerevents3/#implicit-pointer-capture
67+ const target = event .target as HTMLElement
68+ if (target .hasPointerCapture (event .pointerId ))
69+ target .releasePointerCapture (event .pointerId )
70+
71+ // only call handler if it's the left button (mousedown gets triggered by all mouse buttons)
72+ // but not when the control key is pressed (avoiding MacOS right click)
73+ if (isPlainLeftClick (event )) {
74+ handlePointerOpen (event )
75+ openedFromPointerDown = true
76+ }
77+ }
78+
79+ function onTriggerMouseDown(event : MouseEvent ) {
80+ // Prevent trigger from stealing focus from the active item after opening.
81+ // We avoid calling `preventDefault` in `pointerdown` because that suppresses
82+ // compatibility mouse events (`mousedown`, `mouseup`, `click`).
83+ if (isPlainLeftClick (event ))
84+ event .preventDefault ()
85+ }
86+
87+ function onTriggerClick(event : MouseEvent ) {
88+ // Safari: label-associated clicks may not run `pointerdown` on the trigger.
89+ // Direct mouse clicks open in `pointerdown` and must not re-focus the trigger
90+ // here — `mousedown` `preventDefault` does not suppress `click`.
91+ if (! openedFromPointerDown )
92+ (event .currentTarget as HTMLElement )?.focus ()
93+
94+ openedFromPointerDown = false
95+ }
5096 </script >
5197
5298<template >
@@ -69,39 +115,9 @@ function handlePointerOpen(event: PointerEvent) {
69115 :data-placeholder =" shouldShowPlaceholder (rootContext .modelValue ?.value ) ? ' ' : undefined "
70116 :as-child =" asChild "
71117 :as =" as "
72- @click ="
73- (event : MouseEvent ) => {
74- // Whilst browsers generally have no issue focusing the trigger when clicking
75- // on a label, Safari seems to struggle with the fact that there's no `onClick`.
76- // We force `focus` in this case. Note: this doesn't create any other side-effect
77- // because we are preventing default in `onPointerDown` so effectively
78- // this only runs for a label 'click'
79- (event ?.currentTarget as HTMLElement )?.focus ();
80- }
81- "
82- @pointerdown ="
83- (event : PointerEvent ) => {
84- // Prevent opening on touch down.
85- // https://github.com/unovue/reka-ui/issues/804
86- if (event .pointerType === ' touch' )
87- return event .preventDefault ();
88-
89- // prevent implicit pointer capture
90- // https://www.w3.org/TR/pointerevents3/#implicit-pointer-capture
91- const target = event .target as HTMLElement ;
92- if (target .hasPointerCapture (event .pointerId )) {
93- target .releasePointerCapture (event .pointerId );
94- }
95-
96- // only call handler if it's the left button (mousedown gets triggered by all mouse buttons)
97- // but not when the control key is pressed (avoiding MacOS right click)
98- if (event .button === 0 && event .ctrlKey === false ) {
99- handlePointerOpen (event )
100- // prevent trigger from stealing focus from the active item after opening.
101- event .preventDefault ();
102- }
103- }
104- "
118+ @click =" onTriggerClick "
119+ @pointerdown =" onTriggerPointerDown "
120+ @mousedown =" onTriggerMouseDown "
105121 @pointerup .prevent ="
106122 (event : PointerEvent ) => {
107123 // Only open on pointer up when using touch devices
0 commit comments