From 329948cf4cc09306ee460c288df256ba900ce982 Mon Sep 17 00:00:00 2001 From: bruno Date: Sun, 12 Jul 2026 16:25:13 -0400 Subject: [PATCH] fix: repositionnement dynamique du menu contextuel dans le viewport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remplacé le clamping statique (Math.min 200/300) par mesure réelle du menu après rendu DOM via $nextTick + getBoundingClientRect() - Si le menu dépasse à droite → repositionné à gauche - Si le menu dépasse en bas → repositionné vers le haut - Marge de 4px des bords pour éviter le clipping - Fonctionne pour toutes les tailles de menu (tags, sous-menus dépliés) --- app/templates/local_workspace.html | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/app/templates/local_workspace.html b/app/templates/local_workspace.html index 9498e88..7beba69 100644 --- a/app/templates/local_workspace.html +++ b/app/templates/local_workspace.html @@ -1257,28 +1257,41 @@ document.addEventListener('alpine:init', function() { // ── Context menu ── onContextMenu(ev) { - // Find closest element with data-ws-id (works on all views) var el = ev.target.closest('[data-ws-id]'); if (!el) { this.ctxMenu.visible = false; return; } var id = parseInt(el.getAttribute('data-ws-id')); if (!id) { this.ctxMenu.visible = false; return; } - // Find node in tree var node = this._findNodeById(this.displayTree, id); if (!node) { this.ctxMenu.visible = false; return; } this.ctxMenu = { visible: true, - x: Math.min(ev.clientX, window.innerWidth - 200), - y: Math.min(ev.clientY, window.innerHeight - 300), + x: ev.clientX, + y: ev.clientY, node: node, tags: [...(node.tags||[])] }; this.ctxTagAdding = false; this.ctxTagExistingOpen = false; this.ctxNewTagColor = '#787774'; - // Load available tags (not already on the item) + // Load available tags this.ctxAvailTags = (this.workspaceTags || []).filter(function(t) { return !(node.tags||[]).some(function(nt) { return nt.id === t.id; }); }); + // Reposition after DOM update + var self = this; + self.$nextTick(function() { + var menu = self.$el.querySelector('.ctx-menu'); + if (!menu) return; + var rect = menu.getBoundingClientRect(); + var x = self.ctxMenu.x; + var y = self.ctxMenu.y; + if (x + rect.width > window.innerWidth - 4) x = window.innerWidth - rect.width - 4; + if (y + rect.height > window.innerHeight - 4) y = window.innerHeight - rect.height - 4; + if (x < 4) x = 4; + if (y < 4) y = 4; + self.ctxMenu.x = x; + self.ctxMenu.y = y; + }); }, ctxAddExistingTag(tag) {