Skip to content

Commit b4093a1

Browse files
committed
fix: close three dots menu dropdown on click outside
1 parent caca799 commit b4093a1

File tree

1 file changed

+22
-1
lines changed

1 file changed

+22
-1
lines changed

adminforth/spa/src/components/ThreeDotsMenu.vue

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<template >
22
<div class="relative" v-if="threeDotsDropdownItems?.length || customActions?.length || (bulkActions?.some((action: AdminForthBulkActionCommon) => action.showInThreeDotsDropdown))">
33
<button
4+
ref="buttonTriggerRef"
45
@click="toggleDropdownVisibility"
56
class="flex items-center py-2 px-2 text-sm font-medium text-lightThreeDotsMenuIconDots focus:outline-none bg-lightThreeDotsMenuIconBackground rounded border border-lightThreeDotsMenuIconBackgroundBorder hover:bg-lightThreeDotsMenuIconBackgroundHover hover:text-lightThreeDotsMenuIconDotsHover focus:z-10 focus:ring-4 focus:ring-lightThreeDotsMenuIconFocus dark:focus:ring-darkThreeDotsMenuIconFocus dark:bg-darkThreeDotsMenuIconBackground dark:text-darkThreeDotsMenuIconDots dark:border-darkThreeDotsMenuIconBackgroundBorder dark:hover:text-darkThreeDotsMenuIconDotsHover dark:hover:bg-darkThreeDotsMenuIconBackgroundHover rounded-default"
67
>
@@ -12,6 +13,7 @@
1213
<!-- Dropdown menu -->
1314
<div
1415
v-if="showDropdown"
16+
ref="dropdownRef"
1517
class="absolute z-30 right-0 mt-3 bg-lightThreeDotsMenuBodyBackground divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-darkThreeDotsMenuBodyBackground dark:divide-gray-600">
1618
<ul class="py-2 text-sm text-lightThreeDotsMenuBodyText dark:text-darkThreeDotsMenuBodyText" aria-labelledby="dropdownMenuIconButton">
1719
<li v-for="(item, i) in threeDotsDropdownItems" :key="`dropdown-item-${i}`">
@@ -82,7 +84,7 @@ import adminforth from '@/adminforth';
8284
import { callAdminForthApi } from '@/utils';
8385
import { useRoute, useRouter } from 'vue-router';
8486
import CallActionWrapper from '@/components/CallActionWrapper.vue'
85-
import { ref, type ComponentPublicInstance } from 'vue';
87+
import { ref, type ComponentPublicInstance, onMounted, onUnmounted } from 'vue';
8688
import type { AdminForthBulkActionCommon, AdminForthComponentDeclarationFull } from '@/types/Common';
8789
import type { AdminForthActionInput } from '@/types/Back';
8890
@@ -92,6 +94,8 @@ const coreStore = useCoreStore();
9294
const router = useRouter();
9395
const threeDotsDropdownItemsRefs = ref<Array<ComponentPublicInstance | null>>([]);
9496
const showDropdown = ref(false);
97+
const dropdownRef = ref<HTMLElement | null>(null);
98+
const buttonTriggerRef = ref<HTMLElement | null>(null);
9599
96100
const props = defineProps({
97101
threeDotsDropdownItems: Array<AdminForthComponentDeclarationFull>,
@@ -182,4 +186,21 @@ async function injectedComponentClick(index: number) {
182186
function toggleDropdownVisibility() {
183187
showDropdown.value = !showDropdown.value;
184188
}
189+
190+
function handleClickOutside(e: MouseEvent) {
191+
if (!dropdownRef.value) return
192+
193+
if (!dropdownRef.value.contains(e.target as Node) && !buttonTriggerRef.value?.contains(e.target as Node)) {
194+
showDropdown.value = false;
195+
}
196+
}
197+
198+
onMounted(() => {
199+
document.addEventListener('mousedown', handleClickOutside)
200+
})
201+
202+
onUnmounted(() => {
203+
document.removeEventListener('mousedown', handleClickOutside)
204+
})
205+
185206
</script>

0 commit comments

Comments
 (0)