ui: custom project switcher dropdown — no native select
This commit is contained in:
parent
a2fc510065
commit
a9d40a31b5
|
|
@ -216,28 +216,6 @@ input:focus, textarea:focus, select:focus { border-color: var(--ds-ac) !importan
|
|||
/* ===== TREE TABLE ===== */
|
||||
#reqTree { border-collapse: collapse; width: 100%; font-size: 13px; }
|
||||
|
||||
/* ===== PROJECT SWITCHER ===== */
|
||||
#projectSwitcher {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
color: var(--ds-tx);
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
max-width: 320px;
|
||||
}
|
||||
#projectSwitcher option {
|
||||
background: var(--ds-sf);
|
||||
color: var(--ds-tx);
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* ===== TYPE HIERARCHY ===== */
|
||||
/* Level 1 — Logo / Page title : 2xl (19.5px) — set inline */
|
||||
/* Level 2 — Project name in header : xl (16.25px) — set inline */
|
||||
|
|
|
|||
|
|
@ -2,10 +2,14 @@
|
|||
<div class="flex items-center gap-3">
|
||||
<a href="/app/projects" class="text-2xl font-bold text-white tracking-tight"><span class="text-[#c9a84c]">Deal</span>space</a>
|
||||
<span class="text-white/20 text-lg">/</span>
|
||||
<select id="projectSwitcher" onchange="switchProject(this.value)"
|
||||
class="bg-transparent border-none outline-none text-xl font-semibold text-white cursor-pointer focus:outline-none">
|
||||
<option id="projectName" value="">Loading...</option>
|
||||
</select>
|
||||
<div id="projectSwitcher" class="relative">
|
||||
<button id="projectSwitcherBtn" onclick="toggleProjectMenu()" class="flex items-center gap-1.5 text-xl font-semibold text-white hover:text-white/80 transition focus:outline-none">
|
||||
<span id="projectName">Loading...</span>
|
||||
<span style="font-size:10px;opacity:.5;margin-top:2px">▾</span>
|
||||
</button>
|
||||
<div id="projectMenu" class="hidden absolute left-0 top-full mt-2 min-w-[220px] rounded-lg border shadow-xl z-50" style="background:var(--ds-sf);border-color:var(--ds-bd)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
|
|
@ -331,25 +335,18 @@
|
|||
const d = parseData(p.data_text);
|
||||
const name = d.name || p.summary_text || p.summary || 'Untitled';
|
||||
document.title = name + ' — Dealspace';
|
||||
// Populate project switcher
|
||||
const sel = document.getElementById('projectSwitcher');
|
||||
const opt = document.getElementById('projectName');
|
||||
opt.value = projectID;
|
||||
opt.textContent = name;
|
||||
// Load all projects for switcher
|
||||
document.getElementById('projectName').textContent = name;
|
||||
fetchAPI('/api/projects').then(r=>r.json()).then(projects=>{
|
||||
sel.innerHTML = '';
|
||||
(projects||[]).forEach(p=>{
|
||||
const o = document.createElement('option');
|
||||
o.value = p.entry_id;
|
||||
const menu = document.getElementById('projectMenu');
|
||||
menu.innerHTML = (projects||[]).map(p=>{
|
||||
const d = p.data_text ? (()=>{try{return JSON.parse(p.data_text)}catch{return{}}})() : {};
|
||||
o.textContent = d.name || p.search_key || p.entry_id;
|
||||
if(p.entry_id === projectID) o.selected = true;
|
||||
sel.appendChild(o);
|
||||
});
|
||||
}).catch(()=>{
|
||||
sel.innerHTML = `<option value="${projectID}">${name}</option>`;
|
||||
});
|
||||
const pname = d.name || p.search_key || p.entry_id;
|
||||
const active = p.entry_id === projectID;
|
||||
return `<div onclick="switchProject('${p.entry_id}')" class="px-4 py-2.5 cursor-pointer transition text-sm" style="color:${active?'var(--ds-ac)':'var(--ds-tx)'};background:${active?'rgba(255,255,255,.04)':'transparent'}" onmouseover="this.style.background='rgba(255,255,255,.06)'" onmouseout="this.style.background='${active?'rgba(255,255,255,.04)':'transparent'}'">
|
||||
${escHtml(pname)}
|
||||
</div>`;
|
||||
}).join('');
|
||||
}).catch(()=>{});
|
||||
// projectTitle removed — name shown in header breadcrumb only
|
||||
document.getElementById('projectDesc').textContent = d.description || '';
|
||||
const status = d.status || 'active';
|
||||
|
|
@ -898,8 +895,16 @@
|
|||
}
|
||||
|
||||
function switchProject(pid) {
|
||||
document.getElementById('projectMenu').classList.add('hidden');
|
||||
if (pid && pid !== projectID) window.location.href = '/app/projects/' + pid;
|
||||
}
|
||||
function toggleProjectMenu() {
|
||||
document.getElementById('projectMenu').classList.toggle('hidden');
|
||||
}
|
||||
document.addEventListener('click', e => {
|
||||
if (!document.getElementById('projectSwitcher')?.contains(e.target))
|
||||
document.getElementById('projectMenu')?.classList.add('hidden');
|
||||
});
|
||||
|
||||
function closeAddOrgModal() {
|
||||
document.getElementById('addOrgModal').classList.add('hidden');
|
||||
|
|
|
|||
Loading…
Reference in New Issue