summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-02-25 13:44:37 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-02-25 13:44:37 +0900
commite7a1046b872ebc4aaa010fb3190a0225b13358fb (patch)
tree3e88d5b506bf5895feb4c5ca50074288ba714d2e /packages
parentUpdate CHANGELOG.md (diff)
downloadsharkey-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.vue10
-rw-r--r--packages/frontend/src/components/MkMenu.child.vue35
-rw-r--r--packages/frontend/src/components/MkModal.vue23
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;