diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2023-02-25 13:44:37 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2023-02-25 13:44:37 +0900 |
| commit | e7a1046b872ebc4aaa010fb3190a0225b13358fb (patch) | |
| tree | 3e88d5b506bf5895feb4c5ca50074288ba714d2e /packages | |
| parent | Update CHANGELOG.md (diff) | |
| download | sharkey-e7a1046b872ebc4aaa010fb3190a0225b13358fb.tar.gz sharkey-e7a1046b872ebc4aaa010fb3190a0225b13358fb.tar.bz2 sharkey-e7a1046b872ebc4aaa010fb3190a0225b13358fb.zip | |
enhance(client): tweak contextmenu position calculation
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/frontend/src/components/MkContextMenu.vue | 10 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkMenu.child.vue | 35 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkModal.vue | 23 |
3 files changed, 45 insertions, 23 deletions
diff --git a/packages/frontend/src/components/MkContextMenu.vue b/packages/frontend/src/components/MkContextMenu.vue index f0ea984c4e..21cccaabde 100644 --- a/packages/frontend/src/components/MkContextMenu.vue +++ b/packages/frontend/src/components/MkContextMenu.vue @@ -32,6 +32,8 @@ let rootEl = $shallowRef<HTMLDivElement>(); let zIndex = $ref<number>(os.claimZIndex('high')); +const SCROLLBAR_THICKNESS = 16; + onMounted(() => { let left = props.ev.pageX + 1; // 間違って右ダブルクリックした場合に意図せずアイテムがクリックされるのを防ぐため + 1 let top = props.ev.pageY + 1; // 間違って右ダブルクリックした場合に意図せずアイテムがクリックされるのを防ぐため + 1 @@ -39,12 +41,12 @@ onMounted(() => { const width = rootEl.offsetWidth; const height = rootEl.offsetHeight; - if (left + width - window.pageXOffset > window.innerWidth) { - left = window.innerWidth - width + window.pageXOffset; + if (left + width - window.pageXOffset >= (window.innerWidth - SCROLLBAR_THICKNESS)) { + left = (window.innerWidth - SCROLLBAR_THICKNESS) - width + window.pageXOffset; } - if (top + height - window.pageYOffset > window.innerHeight) { - top = window.innerHeight - height + window.pageYOffset; + if (top + height - window.pageYOffset >= (window.innerHeight - SCROLLBAR_THICKNESS)) { + top = (window.innerHeight - SCROLLBAR_THICKNESS) - height + window.pageYOffset; } if (top < 0) { diff --git a/packages/frontend/src/components/MkMenu.child.vue b/packages/frontend/src/components/MkMenu.child.vue index cdd9d96b96..e0935efbe7 100644 --- a/packages/frontend/src/components/MkMenu.child.vue +++ b/packages/frontend/src/components/MkMenu.child.vue @@ -1,11 +1,11 @@ <template> -<div ref="el" class="sfhdhdhr"> - <MkMenu ref="menu" :items="items" :align="align" :width="width" :as-drawer="false" @close="onChildClosed"/> +<div ref="el" :class="$style.root"> + <MkMenu :items="items" :align="align" :width="width" :as-drawer="false" @close="onChildClosed"/> </div> </template> <script lang="ts" setup> -import { nextTick, onMounted, shallowRef, watch } from 'vue'; +import { nextTick, onMounted, onUnmounted, shallowRef, watch } from 'vue'; import MkMenu from './MkMenu.vue'; import { MenuItem } from '@/types/menu'; @@ -25,11 +25,21 @@ const emit = defineEmits<{ const el = shallowRef<HTMLElement>(); const align = 'left'; +const SCROLLBAR_THICKNESS = 16; + function setPosition() { const rootRect = props.rootElement.getBoundingClientRect(); - const rect = props.targetElement.getBoundingClientRect(); - const left = props.targetElement.offsetWidth; - const top = (rect.top - rootRect.top) - 8; + const parentRect = props.targetElement.getBoundingClientRect(); + const myRect = el.value.getBoundingClientRect(); + + let left = props.targetElement.offsetWidth; + let top = (parentRect.top - rootRect.top) - 8; + if (rootRect.left + left + myRect.width >= (window.innerWidth - SCROLLBAR_THICKNESS)) { + left = -myRect.width; + } + if (rootRect.top + top + myRect.height >= (window.innerHeight - SCROLLBAR_THICKNESS)) { + top = top - ((rootRect.top + top + myRect.height) - (window.innerHeight - SCROLLBAR_THICKNESS)); + } el.value.style.left = left + 'px'; el.value.style.top = top + 'px'; } @@ -46,13 +56,22 @@ watch(() => props.targetElement, () => { setPosition(); }); +const ro = new ResizeObserver((entries, observer) => { + setPosition(); +}); + onMounted(() => { + ro.observe(el.value); setPosition(); nextTick(() => { setPosition(); }); }); +onUnmounted(() => { + ro.disconnect(); +}); + defineExpose({ checkHit: (ev: MouseEvent) => { return (ev.target === el.value || el.value.contains(ev.target)); @@ -60,8 +79,8 @@ defineExpose({ }); </script> -<style lang="scss" scoped> -.sfhdhdhr { +<style lang="scss" module> +.root { position: absolute; } </style> diff --git a/packages/frontend/src/components/MkModal.vue b/packages/frontend/src/components/MkModal.vue index eba0f5847d..dbad02fb7e 100644 --- a/packages/frontend/src/components/MkModal.vue +++ b/packages/frontend/src/components/MkModal.vue @@ -125,7 +125,7 @@ function onBgClick() { } if (type === 'drawer') { - maxHeight = window.innerHeight / 1.5; + maxHeight = (window.innerHeight - SCROLLBAR_THICKNESS) / 1.5; } const keymap = { @@ -133,6 +133,7 @@ const keymap = { }; const MARGIN = 16; +const SCROLLBAR_THICKNESS = 16; const align = () => { if (props.src == null) return; @@ -170,15 +171,15 @@ const align = () => { if (fixed) { // 画面から横にはみ出る場合 - if (left + width > window.innerWidth) { - left = window.innerWidth - width; + if (left + width > (window.innerWidth - SCROLLBAR_THICKNESS)) { + left = (window.innerWidth - SCROLLBAR_THICKNESS) - width; } - const underSpace = (window.innerHeight - MARGIN) - top; + const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - top; const upperSpace = (srcRect.top - MARGIN); // 画面から縦にはみ出る場合 - if (top + height > (window.innerHeight - MARGIN)) { + if (top + height > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) { if (props.noOverlap && props.anchor.x === 'center') { if (underSpace >= (upperSpace / 3)) { maxHeight = underSpace; @@ -187,22 +188,22 @@ const align = () => { top = (upperSpace + MARGIN) - height; } } else { - top = (window.innerHeight - MARGIN) - height; + top = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - height; } } else { maxHeight = underSpace; } } else { // 画面から横にはみ出る場合 - if (left + width - window.pageXOffset > window.innerWidth) { - left = window.innerWidth - width + window.pageXOffset - 1; + if (left + width - window.pageXOffset > (window.innerWidth - SCROLLBAR_THICKNESS)) { + left = (window.innerWidth - SCROLLBAR_THICKNESS) - width + window.pageXOffset - 1; } - const underSpace = (window.innerHeight - MARGIN) - (top - window.pageYOffset); + const underSpace = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - (top - window.pageYOffset); const upperSpace = (srcRect.top - MARGIN); // 画面から縦にはみ出る場合 - if (top + height - window.pageYOffset > (window.innerHeight - MARGIN)) { + if (top + height - window.pageYOffset > ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN)) { if (props.noOverlap && props.anchor.x === 'center') { if (underSpace >= (upperSpace / 3)) { maxHeight = underSpace; @@ -211,7 +212,7 @@ const align = () => { top = window.pageYOffset + ((upperSpace + MARGIN) - height); } } else { - top = (window.innerHeight - MARGIN) - height + window.pageYOffset - 1; + top = ((window.innerHeight - SCROLLBAR_THICKNESS) - MARGIN) - height + window.pageYOffset - 1; } } else { maxHeight = underSpace; |