Fix context menu positioning and remove unnecessary width
This commit is contained in:
+42
-9
@@ -436,7 +436,6 @@ function contextMenuElements() {
|
||||
return {
|
||||
menu: document.getElementById("context-menu"),
|
||||
scope: document.getElementById("context-menu-scope"),
|
||||
target: document.getElementById("context-menu-target"),
|
||||
openButton: document.getElementById("context-menu-open-btn"),
|
||||
editButton: document.getElementById("context-menu-edit-btn"),
|
||||
downloadButton: document.getElementById("context-menu-download-btn"),
|
||||
@@ -774,7 +773,8 @@ function closeContextMenu() {
|
||||
}
|
||||
elements.menu.classList.add("hidden");
|
||||
elements.scope.textContent = "";
|
||||
elements.target.textContent = "";
|
||||
elements.menu.style.left = "";
|
||||
elements.menu.style.top = "";
|
||||
}
|
||||
|
||||
function openContextMenu(pane, entry, event) {
|
||||
@@ -800,7 +800,6 @@ function openContextMenu(pane, entry, event) {
|
||||
const editableSingle = items.length === 1 && !remoteSelection && isEditableSelection(items[0]);
|
||||
const downloadableSelection = items.length === 1 && items[0].kind === "file";
|
||||
elements.scope.textContent = isMulti ? "Multi-selection" : "Single item";
|
||||
elements.target.textContent = isMulti ? `${items.length} selected items` : entry.name;
|
||||
elements.openButton.classList.toggle("hidden", isMulti);
|
||||
elements.openButton.disabled = !openableSingle;
|
||||
elements.editButton.classList.toggle("hidden", isMulti || items.length !== 1 || items[0].kind !== "file" || remoteSelection);
|
||||
@@ -819,13 +818,47 @@ function openContextMenu(pane, entry, event) {
|
||||
elements.propertiesButton.classList.remove("hidden");
|
||||
elements.propertiesButton.disabled = items.length === 0;
|
||||
|
||||
const menuWidth = 220;
|
||||
const menuHeight = 120;
|
||||
const x = Math.min(event.clientX, window.innerWidth - menuWidth - 12);
|
||||
const y = Math.min(event.clientY, window.innerHeight - menuHeight - 12);
|
||||
elements.menu.style.left = `${Math.max(8, x)}px`;
|
||||
elements.menu.style.top = `${Math.max(8, y)}px`;
|
||||
elements.menu.classList.remove("hidden");
|
||||
positionContextMenu(elements.menu, event.currentTarget, event);
|
||||
}
|
||||
|
||||
function positionContextMenu(menu, rowElement, event) {
|
||||
if (!menu) {
|
||||
return;
|
||||
}
|
||||
const paneElement = rowElement instanceof Element ? rowElement.closest(".pane") : null;
|
||||
const paneRect = paneElement ? paneElement.getBoundingClientRect() : null;
|
||||
const rowRect = rowElement instanceof Element ? rowElement.getBoundingClientRect() : null;
|
||||
const menuRect = menu.getBoundingClientRect();
|
||||
const viewportPadding = 8;
|
||||
const panePadding = 8;
|
||||
|
||||
const minLeft = paneRect ? Math.max(viewportPadding, paneRect.left + panePadding) : viewportPadding;
|
||||
const maxLeft = paneRect
|
||||
? Math.max(minLeft, Math.min(window.innerWidth - viewportPadding - menuRect.width, paneRect.right - panePadding - menuRect.width))
|
||||
: Math.max(minLeft, window.innerWidth - viewportPadding - menuRect.width);
|
||||
const preferredLeft = rowRect ? rowRect.left + 12 : event.clientX;
|
||||
const left = Math.max(minLeft, Math.min(maxLeft, preferredLeft));
|
||||
|
||||
const paneTop = paneRect ? paneRect.top + panePadding : viewportPadding;
|
||||
const paneBottom = paneRect ? paneRect.bottom - panePadding : window.innerHeight - viewportPadding;
|
||||
const rowTop = rowRect ? rowRect.top : event.clientY;
|
||||
const rowBottom = rowRect ? rowRect.bottom : event.clientY;
|
||||
const spaceBelow = paneBottom - rowBottom;
|
||||
const spaceAbove = rowTop - paneTop;
|
||||
|
||||
let top;
|
||||
if (spaceBelow >= menuRect.height || spaceBelow >= spaceAbove) {
|
||||
top = rowBottom;
|
||||
} else if (spaceAbove >= menuRect.height) {
|
||||
top = rowTop - menuRect.height;
|
||||
} else {
|
||||
top = Math.max(paneTop, Math.min(paneBottom - menuRect.height, rowBottom));
|
||||
}
|
||||
top = Math.max(paneTop, Math.min(top, paneBottom - menuRect.height));
|
||||
|
||||
menu.style.left = `${left}px`;
|
||||
menu.style.top = `${top}px`;
|
||||
}
|
||||
|
||||
function applyContextMenuSelection() {
|
||||
|
||||
+8
-12
@@ -907,7 +907,11 @@ button:disabled {
|
||||
|
||||
.context-menu {
|
||||
position: fixed;
|
||||
min-width: 220px;
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
width: max-content;
|
||||
max-width: min(196px, calc(100vw - 24px));
|
||||
padding: 8px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-sm);
|
||||
@@ -924,24 +928,16 @@ button:disabled {
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
|
||||
.context-menu-target {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--color-text-primary);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.context-menu-separator {
|
||||
height: 1px;
|
||||
margin: 8px 0;
|
||||
margin: 6px 0 8px;
|
||||
background: var(--color-border);
|
||||
}
|
||||
|
||||
.context-menu button {
|
||||
width: 100%;
|
||||
width: auto;
|
||||
justify-content: flex-start;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#upload-modal .popup-card {
|
||||
|
||||
@@ -161,7 +161,6 @@
|
||||
|
||||
<div id="context-menu" class="context-menu hidden" role="menu" aria-label="Item context menu">
|
||||
<div id="context-menu-scope" class="context-menu-scope"></div>
|
||||
<div id="context-menu-target" class="context-menu-target"></div>
|
||||
<div class="context-menu-separator"></div>
|
||||
<button id="context-menu-open-btn" type="button" role="menuitem">Open</button>
|
||||
<button id="context-menu-edit-btn" type="button" role="menuitem">Edit</button>
|
||||
|
||||
Reference in New Issue
Block a user