fix: close message generation popover when its trigger scrolls away (#15114)
This commit is contained in:
@@ -234,6 +234,7 @@ onMounted(() => resetContacts());
|
||||
ref="popoverRef"
|
||||
:align="align"
|
||||
:show-content-border="false"
|
||||
:close-on-scroll="false"
|
||||
@show="onPopoverShow"
|
||||
@hide="onPopoverHide"
|
||||
>
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<script setup>
|
||||
import { ref, computed, watch, nextTick } from 'vue';
|
||||
import { vOnClickOutside } from '@vueuse/components';
|
||||
import { useBreakpoints, breakpointsTailwind } from '@vueuse/core';
|
||||
import {
|
||||
useBreakpoints,
|
||||
breakpointsTailwind,
|
||||
useEventListener,
|
||||
} from '@vueuse/core';
|
||||
import { useDropdownPosition } from 'dashboard/composables/useDropdownPosition';
|
||||
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
|
||||
import TeleportWithDirection from 'dashboard/components-next/TeleportWithDirection.vue';
|
||||
@@ -16,6 +20,10 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
closeOnScroll: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showContentBorder: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
@@ -41,8 +49,12 @@ const { fixedPosition, updatePosition } = useDropdownPosition(
|
||||
{ align: props.align }
|
||||
);
|
||||
|
||||
const SCROLL_CLOSE_THRESHOLD = 24;
|
||||
const triggerTopAtOpen = ref(0);
|
||||
|
||||
const show = async () => {
|
||||
isActive.value = true;
|
||||
triggerTopAtOpen.value = triggerRef.value?.getBoundingClientRect().top ?? 0;
|
||||
if (!isMobile.value) {
|
||||
await nextTick();
|
||||
updatePosition();
|
||||
@@ -56,6 +68,22 @@ const hide = () => {
|
||||
emit('hide');
|
||||
};
|
||||
|
||||
// The teleported popover tracks its trigger while ancestors scroll; allow
|
||||
// small drift (trackpad inertia), but close once the trigger moves further.
|
||||
useEventListener(
|
||||
window,
|
||||
'scroll',
|
||||
event => {
|
||||
if (!props.closeOnScroll || !showPopover.value) return;
|
||||
if (popoverRef.value?.contains(event.target)) return;
|
||||
const top = triggerRef.value?.getBoundingClientRect().top ?? 0;
|
||||
if (Math.abs(top - triggerTopAtOpen.value) > SCROLL_CLOSE_THRESHOLD) {
|
||||
hide();
|
||||
}
|
||||
},
|
||||
{ capture: true, passive: true }
|
||||
);
|
||||
|
||||
const toggle = async () => {
|
||||
if (isActive.value) hide();
|
||||
else await show();
|
||||
|
||||
Reference in New Issue
Block a user