fix: Prevent menu from overflowing off screen

Co-authored-by: Lhcfl <Lhcfl@outlook.com>
This commit is contained in:
Linca 2024-05-21 14:38:19 +00:00 committed by naskya
parent 0c0e6a26fa
commit e8accfaabb
4 changed files with 31 additions and 3 deletions

View file

@ -12,7 +12,7 @@
</template>
<script lang="ts" setup>
import { nextTick, onMounted, ref } from "vue";
import { nextTick, onMounted, ref, watch } from "vue";
import MkMenu from "./MkMenu.vue";
import type { MenuItem } from "@/types/menu";
@ -35,7 +35,13 @@ const align = "left";
function setPosition() {
const rootRect = props.rootElement.getBoundingClientRect();
const rect = props.targetElement.getBoundingClientRect();
const left = props.targetElement.offsetWidth;
let left = props.targetElement.offsetWidth;
if (rootRect.x + left > window.innerWidth - rect.width) {
left = -rect.width;
}
if (rect.x + left < 0) {
left = -rect.x;
}
const top = rect.top - rootRect.top - 8;
el.value!.style.left = `${left}px`;
el.value!.style.top = `${top}px`;
@ -56,6 +62,15 @@ onMounted(() => {
});
});
watch(
() => props.items,
() => {
nextTick(() => {
setPosition();
});
},
);
defineExpose({
checkHit: (ev: MouseEvent) => {
return ev.target === el.value || el.value?.contains(ev.target as Node);

View file

@ -250,7 +250,7 @@ const align = () => {
if (props.anchor.x === "center") {
left = x + props.src.offsetWidth / 2 - width / 2;
} else if (props.anchor.x === "left") {
// TODO
left = x + props.src.offsetWidth - width;
} else if (props.anchor.x === "right") {
left = x + props.src.offsetWidth;
}
@ -317,6 +317,9 @@ const align = () => {
top = MARGIN;
}
if (left > window.innerWidth - width - MARGIN) {
left = window.innerWidth - width - MARGIN;
}
if (left < 0) {
left = 0;
}

View file

@ -5,6 +5,7 @@
:z-priority="'high'"
:src="src"
:transparent-bg="true"
:anchor
tabindex="-1"
@click="modal?.close()"
@closed="emit('closed')"
@ -36,6 +37,10 @@ defineProps<{
width?: number;
viaKeyboard?: boolean;
src?: HTMLElement | null;
anchor?: {
x: "left" | "center" | "right";
y: "top" | "center" | "bottom";
};
noReturnFocus?;
}>();

View file

@ -916,6 +916,10 @@ export function popupMenu(
width?: number;
viaKeyboard?: boolean;
noReturnFocus?: boolean;
anchor?: {
x: "left" | "center" | "right";
y: "top" | "center" | "bottom";
};
},
) {
return new Promise<void>((resolve, _reject) => {
@ -929,6 +933,7 @@ export function popupMenu(
{
items,
src,
anchor: options?.anchor,
width: options?.width,
align: options?.align,
viaKeyboard: options?.viaKeyboard,