v1.8.34: fix dropdown — portal to body with fixed positioning, no overlap possible

This commit is contained in:
2026-05-28 23:12:57 +00:00
parent 43d72c757d
commit 97653ef882
+36 -21
View File
@@ -181,29 +181,44 @@
if (!r.ok) { localStorage.removeItem('rag_token'); initHeaderAuth(); return; } if (!r.ok) { localStorage.removeItem('rag_token'); initHeaderAuth(); return; }
const user = await r.json(); const user = await r.json();
const isAdmin = user.role === 'admin'; const isAdmin = user.role === 'admin';
// Button only in nav-auth
nav.innerHTML = ` nav.innerHTML = `
<div class="relative" id="uh-wrap"> <button id="uh-btn" class="glass glass-hover flex items-center gap-2 px-3 py-2 rounded-xl text-xs transition-colors">
<button onclick="document.getElementById('uh-drop').classList.toggle('hidden')" <span class="msym text-base text-primary">person</span>
class="glass glass-hover flex items-center gap-2 px-3 py-2 rounded-xl text-xs transition-colors"> <span class="hidden sm:inline max-w-[80px] truncate">${user.name}</span>
<span class="msym text-base text-primary">person</span> <span class="msym text-sm text-on-surface-variant">expand_more</span>
<span class="hidden sm:inline max-w-[80px] truncate">${user.name}</span> </button>`;
<span class="msym text-sm text-on-surface-variant">expand_more</span>
</button> // Dropdown portaled to body — no overlap possible
<div id="uh-drop" class="hidden absolute top-full mt-1 glass rounded-xl p-2 w-44 z-50 shadow-xl" style="left:0;max-width:calc(100vw - 4rem)"> const existingDrop = document.getElementById('uh-drop');
<div class="px-3 py-2 border-b border-outline-variant/30 mb-1"> if (existingDrop) existingDrop.remove();
<p class="text-xs font-bold">${user.name}</p> const drop = document.createElement('div');
<p class="text-[10px] text-primary">${user.role}</p> drop.id = 'uh-drop';
</div> drop.className = 'hidden fixed glass rounded-xl p-2 w-44 z-[9999] shadow-xl';
${isAdmin ? '<a href="/admin" class="flex items-center gap-2 px-3 py-2 rounded-lg text-xs text-on-surface-variant hover:text-primary hover:bg-primary/5"><span class="msym text-sm">admin_panel_settings</span>Admin</a>' : ''} drop.innerHTML = `
<button onclick="uhLogout()" class="w-full flex items-center gap-2 px-3 py-2 rounded-lg text-xs text-error hover:bg-red-900/10"> <div class="px-3 py-2 border-b border-outline-variant/30 mb-1">
<span class="msym text-sm">logout</span>خروج <p class="text-xs font-bold">${user.name}</p>
</button> <p class="text-[10px] text-primary">${user.role}</p>
</div> </div>
</div>`; ${isAdmin ? '<a href="/admin" class="flex items-center gap-2 px-3 py-2 rounded-lg text-xs text-on-surface-variant hover:text-primary hover:bg-primary/5"><span class="msym text-sm">admin_panel_settings</span>Admin</a>' : ''}
document.addEventListener('click', e => { <button onclick="uhLogout()" class="w-full flex items-center gap-2 px-3 py-2 rounded-lg text-xs text-error hover:bg-red-900/10">
const w = document.getElementById('uh-wrap'); <span class="msym text-sm">logout</span>خروج
if (w && !w.contains(e.target)) document.getElementById('uh-drop')?.classList.add('hidden'); </button>`;
document.body.appendChild(drop);
document.getElementById('uh-btn').addEventListener('click', e => {
e.stopPropagation();
const btn = document.getElementById('uh-btn');
const rect = btn.getBoundingClientRect();
drop.style.top = (rect.bottom + 6) + 'px';
drop.style.left = rect.left + 'px';
// Keep within viewport
const rightEdge = rect.left + 176;
if (rightEdge > window.innerWidth - 8) drop.style.left = (window.innerWidth - 184) + 'px';
drop.classList.toggle('hidden');
}); });
document.addEventListener('click', () => drop.classList.add('hidden'));
} catch (e) {} } catch (e) {}
} }