From a87a517b824db1480de0edeaa39a310ffe4cab2f Mon Sep 17 00:00:00 2001 From: Nariman Jelveh Date: Wed, 29 Jul 2026 15:25:51 -0700 Subject: [PATCH] Anchor file row menu to button edge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit File row overflow menus in the dashboard now open anchored to the ⋯ button (below it with right-edge alignment) instead of pointer position, improving placement consistency. UIContextMenu now supports `position.right` for right-edge pinning, and the ⋯ trigger keeps an active visual state while its menu is open so hover styling doesn’t drop when the cursor moves onto the menu. --- src/gui/src/UI/Dashboard/TabFiles.js | 15 +++++++++++++-- src/gui/src/UI/UIContextMenu.js | 11 +++++++++-- src/gui/src/css/dashboard.css | 9 ++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/gui/src/UI/Dashboard/TabFiles.js b/src/gui/src/UI/Dashboard/TabFiles.js index af2e86c14..d44e34c4c 100644 --- a/src/gui/src/UI/Dashboard/TabFiles.js +++ b/src/gui/src/UI/Dashboard/TabFiles.js @@ -3421,8 +3421,19 @@ const TabFiles = { // row would lose all visual state the moment the pointer moves // onto the menu (same treatment as the right-click handler). const releaseCtxState = this.markRowContextMenuOpen(rowElement); - const menu = UIContextMenu({ items: items }); - menu.onClose = releaseCtxState; + // Anchor the menu to the button — below it, right edges aligned — + // rather than at the pointer, and keep the button in its active + // state until the menu closes. + const btnRect = targetElement.getBoundingClientRect(); + targetElement.classList.add('has-open-contextmenu'); + const menu = UIContextMenu({ + items: items, + position: { top: btnRect.bottom, right: btnRect.right }, + }); + menu.onClose = () => { + targetElement.classList.remove('has-open-contextmenu'); + releaseCtxState(); + }; } }, diff --git a/src/gui/src/UI/UIContextMenu.js b/src/gui/src/UI/UIContextMenu.js index 7d051e39b..25287a19e 100644 --- a/src/gui/src/UI/UIContextMenu.js +++ b/src/gui/src/UI/UIContextMenu.js @@ -378,7 +378,9 @@ * @param {string} [options.id] - Unique identifier for the menu * @param {Object} [options.position] - Custom positioning for the menu * @param {number} options.position.top - Top position in pixels - * @param {number} options.position.left - Left position in pixels + * @param {number} [options.position.left] - Left position in pixels (pins the menu's left edge) + * @param {number} [options.position.right] - Right position in pixels (pins the menu's right + * edge instead — for anchoring to right-edge buttons) * @param {boolean|number} [options.delay] - Animation delay for menu appearance * true/1/undefined = 50ms fade * false = no animation @@ -541,7 +543,12 @@ function UIContextMenu (options) { // custom position //-------------------------------- else { - start_x = options.position.left; + // position.right pins the menu's right edge (anchors that sit at + // the right edge of their container would otherwise trigger the + // overflow flip only sometimes, making placement inconsistent) + start_x = options.position.right !== undefined + ? options.position.right - $(contextMenu).outerWidth() + : options.position.left; start_y = options.position.top; } diff --git a/src/gui/src/css/dashboard.css b/src/gui/src/css/dashboard.css index eee5a2711..5952bf1c8 100644 --- a/src/gui/src/css/dashboard.css +++ b/src/gui/src/css/dashboard.css @@ -1821,6 +1821,12 @@ body.myapps-reordering .myapps-tile { } } +/* The '⋯' button stays in its active look while the menu it opened is up + (the pointer is on the menu by then, so :hover alone can't hold it). */ +.dashboard-section-files .row .item-more.has-open-contextmenu { + color: var(--dashboard-text); +} + .dashboard-section-files .row.selected .item-more { color: var(--dashboard-text-secondary); } @@ -2388,7 +2394,8 @@ body.myapps-reordering .myapps-tile { transition: background-color 0.15s ease, color 0.15s ease; } - .dashboard-section-files .files-tab .files.files-grid-view .row .item-more:hover { + .dashboard-section-files .files-tab .files.files-grid-view .row .item-more:hover, + .dashboard-section-files .files-tab .files.files-grid-view .row .item-more.has-open-contextmenu { color: var(--dashboard-text-primary); background: var(--dashboard-hover); }