From c29abe46575e3aa719f6f6fab33d56e0f1cb4515 Mon Sep 17 00:00:00 2001 From: Phan An Date: Sun, 17 Mar 2024 18:37:58 +0100 Subject: [PATCH] feat: better safe triangle for submenus --- .../js/components/ui/ContextMenuBase.vue | 40 ++++++++++++++++--- resources/assets/sass/partials/_shared.scss | 23 ----------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/resources/assets/js/components/ui/ContextMenuBase.vue b/resources/assets/js/components/ui/ContextMenuBase.vue index 2df0f1d9..e7af3d22 100644 --- a/resources/assets/js/components/ui/ContextMenuBase.vue +++ b/resources/assets/js/components/ui/ContextMenuBase.vue @@ -47,11 +47,19 @@ const preventOffScreen = async (element: HTMLElement, isSubmenu = false) => { } } +const safeAreaHeight = ref('0px') +const safeAreaWidth = ref('0px') +const safeAreaClipPath = ref('0 0, 0 0, 0 0, 0 0') + +type MenuItem = HTMLElement & { + eventsRegistered?: boolean +} + const initSubmenus = () => { - el.value?.querySelectorAll('.has-sub').forEach(item => { + el.value?.querySelectorAll('.has-sub').forEach((item: MenuItem) => { const submenu = item.querySelector('.submenu') - if (!submenu) { + if (!submenu || item.eventsRegistered) { return } @@ -61,17 +69,27 @@ const initSubmenus = () => { await preventOffScreen(submenu, true) }) + item.addEventListener('mousemove', async (e: MouseEvent) => { + await nextTick() + const rect = submenu.getBoundingClientRect() + safeAreaHeight.value = rect.height + 'px' + safeAreaWidth.value = rect.x - e.clientX + 'px' + safeAreaClipPath.value = `polygon(100% 0, 0 ${e.clientY - rect.top}px, 100% 100%)` + }) + item.addEventListener('mouseleave', () => { submenu.style.top = '0' submenu.style.bottom = 'auto' submenu.style.display = 'none' }) + + item.eventsRegistered = true }) } -const open = async (_top = 0, _left = 0) => { - top.value = _top - left.value = _left +const open = async (t = 0, l = 0) => { + top.value = t + left.value = l shown.value = true await nextTick() @@ -99,5 +117,17 @@ defineExpose({ open, close, shown }) diff --git a/resources/assets/sass/partials/_shared.scss b/resources/assets/sass/partials/_shared.scss index 0b7bf55e..c4679bcf 100644 --- a/resources/assets/sass/partials/_shared.scss +++ b/resources/assets/sass/partials/_shared.scss @@ -386,29 +386,6 @@ menu { background-repeat: no-repeat; background-position: right 8px center; background-size: 10px; - - &:hover { - &::before, &::after { - content: ''; - display: block; - position: absolute; - right: 0; - width: 75%; - z-index: 2; - - animation: subMenuHoverHelp 1s; - } - - &::before { - clip-path: polygon(100% 0, 0% 100%, 100% 100%); - bottom: 100%; - } - - &::after { - clip-path: polygon(100% 0, 0 0, 100% 100%); - top: 100%; - } - } } }