This commit is contained in:
Daniel Ledda
2023-05-07 21:14:48 +02:00
parent 90a39ee2fe
commit 4268cec832
17 changed files with 800 additions and 2292 deletions

View File

@@ -0,0 +1,81 @@
<template>
<div
class="trigger"
ref="trigger"
@mouseenter="onMouseEnter"
@touchstart="onMouseEnter"
@mouseleave="onMouseLeave">
<slot />
</div>
<Teleport to="#dropdowns">
<div
v-if="visible"
ref="dropdown"
class="dropdown"
:class="{ visible }"
@onmouseleave="visible = false">
<slot name="content" />
</div>
</Teleport>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const trigger = ref<HTMLDivElement>();
const dropdown = ref<HTMLDivElement>();
const visible = ref(false);
const top = ref('0px');
const left = ref('0px');
function onMouseEnter(e: MouseEvent | TouchEvent) {
visible.value = true;
if (trigger.value) {
const rect = trigger.value.getBoundingClientRect();
top.value = rect.top + 'px';
left.value = rect.width + rect.left + 'px';
}
window.addEventListener('touchstart', onWindowClick);
window.addEventListener('click', onWindowClick);
}
function outside(e: MouseEvent, el: HTMLElement) {
const rect = el.getBoundingClientRect();
return e.clientX < rect.x
|| e.clientX > rect.x + rect.width
|| e.clientY < rect.y
|| e.clientY > rect.y + rect.height;
}
function onWindowClick(e: MouseEvent | TouchEvent) {
if (visible.value && e instanceof MouseEvent && dropdown.value && !outside(e, dropdown.value)) {
visible.value = false;
window.removeEventListener('touchstart', onWindowClick);
window.removeEventListener('click', onWindowClick);
}
}
function onMouseLeave(e: MouseEvent) {
if (trigger.value && outside(e, trigger.value)) {
visible.value = false;
}
}
</script>
<style scoped lang="scss">
.dropdown {
position: absolute;
top: v-bind(top);
left: v-bind(left);
visibility: hidden;
&.visible {
visibility: visible;
}
&:hover {
visibility: visible;
}
}
</style>