fix: subcategory accordion navigation, nav link white flash, collapsible sections
This commit is contained in:
parent
ad32ab3d63
commit
b7c20e732e
3 changed files with 66 additions and 12 deletions
|
|
@ -83,7 +83,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "RECON",
|
"label": "RECON",
|
||||||
"url": "/depot/recon"
|
"url": "/recon"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -595,16 +595,34 @@
|
||||||
|
|
||||||
/* ─── Subcategory Group Headings (Awesomelist) ─────────── */
|
/* ─── Subcategory Group Headings (Awesomelist) ─────────── */
|
||||||
.crt-subcat-group {
|
.crt-subcat-group {
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
.crt-subcat-heading {
|
.crt-subcat-heading {
|
||||||
font-family: 'Orbitron', monospace;
|
font-family: 'Orbitron', monospace;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
color: rgba(255, 170, 0, 0.8);
|
color: rgba(255, 170, 0, 0.8);
|
||||||
letter-spacing: 2px;
|
letter-spacing: 2px;
|
||||||
padding: 0.6rem 0;
|
padding: 0.6rem 0.8rem;
|
||||||
border-bottom: 1px solid rgba(255, 170, 0, 0.15);
|
border-bottom: 1px solid rgba(255, 170, 0, 0.15);
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
transition: background 0.2s, color 0.2s;
|
||||||
|
}
|
||||||
|
.crt-subcat-heading:hover {
|
||||||
|
background: rgba(255, 170, 0, 0.06);
|
||||||
|
color: rgba(255, 170, 0, 1);
|
||||||
|
}
|
||||||
|
.crt-subcat-heading.expanded {
|
||||||
|
background: rgba(255, 170, 0, 0.08);
|
||||||
|
border-bottom-color: rgba(255, 170, 0, 0.3);
|
||||||
|
}
|
||||||
|
.crt-subcat-arrow {
|
||||||
|
display: inline-block;
|
||||||
|
width: 1rem;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
color: rgba(255, 170, 0, 0.6);
|
||||||
|
transition: transform 0.2s;
|
||||||
}
|
}
|
||||||
.crt-subcat-count {
|
.crt-subcat-count {
|
||||||
font-family: 'JetBrains Mono', monospace;
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
|
@ -612,3 +630,8 @@
|
||||||
color: #666;
|
color: #666;
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
.crt-subcat-entries {
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
border-left: 1px solid rgba(255, 170, 0, 0.1);
|
||||||
|
margin-left: 0.4rem;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@
|
||||||
// ─── Render: Sector Detail ───────────────────────────
|
// ─── Render: Sector Detail ───────────────────────────
|
||||||
function renderSector(sec) {
|
function renderSector(sec) {
|
||||||
state.view = 'detail';
|
state.view = 'detail';
|
||||||
|
state.currentSector = sec;
|
||||||
let html = '';
|
let html = '';
|
||||||
|
|
||||||
// Back button
|
// Back button
|
||||||
|
|
@ -203,7 +204,9 @@
|
||||||
// ─── Event Bindings: Index ───────────────────────────
|
// ─── Event Bindings: Index ───────────────────────────
|
||||||
function bindIndexEvents() {
|
function bindIndexEvents() {
|
||||||
document.querySelectorAll('.crt-card').forEach(card => {
|
document.querySelectorAll('.crt-card').forEach(card => {
|
||||||
card.addEventListener('click', () => {
|
card.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
loadSector(card.dataset.slug);
|
loadSector(card.dataset.slug);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -232,13 +235,18 @@
|
||||||
// ─── Event Bindings: Detail ──────────────────────────
|
// ─── Event Bindings: Detail ──────────────────────────
|
||||||
function bindDetailEvents(sec) {
|
function bindDetailEvents(sec) {
|
||||||
// Back button
|
// Back button
|
||||||
document.getElementById('crtBack').addEventListener('click', () => {
|
document.getElementById('crtBack').addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
loadIndex();
|
loadIndex();
|
||||||
});
|
});
|
||||||
|
|
||||||
// List card clicks — show all subcategories and entries for that source list
|
// List card clicks — show all subcategories and entries for that source list
|
||||||
document.querySelectorAll('.crt-sub-card').forEach(card => {
|
document.querySelectorAll('.crt-sub-card').forEach(card => {
|
||||||
card.addEventListener('click', () => {
|
card.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
const idx = parseInt(card.dataset.listIdx);
|
const idx = parseInt(card.dataset.listIdx);
|
||||||
const lst = sec.lists[idx];
|
const lst = sec.lists[idx];
|
||||||
const panel = document.getElementById('crtSubDetail');
|
const panel = document.getElementById('crtSubDetail');
|
||||||
|
|
@ -262,9 +270,10 @@
|
||||||
notesEl.innerHTML = '';
|
notesEl.innerHTML = '';
|
||||||
notesEl.style.display = 'none';
|
notesEl.style.display = 'none';
|
||||||
|
|
||||||
// Build entries grouped by subcategory
|
// Build entries grouped by subcategory with collapsible headings
|
||||||
let eh = '';
|
let eh = '';
|
||||||
for (const sub of lst.subcategories) {
|
for (let si = 0; si < lst.subcategories.length; si++) {
|
||||||
|
const sub = lst.subcategories[si];
|
||||||
if (sub.entries.length === 0) continue;
|
if (sub.entries.length === 0) continue;
|
||||||
// Strip the source prefix from subcategory name if it starts with list name
|
// Strip the source prefix from subcategory name if it starts with list name
|
||||||
let subName = sub.name;
|
let subName = sub.name;
|
||||||
|
|
@ -274,13 +283,35 @@
|
||||||
}
|
}
|
||||||
if (subName === lst.name) subName = 'General';
|
if (subName === lst.name) subName = 'General';
|
||||||
|
|
||||||
eh += `<div class="crt-subcat-group">`;
|
eh += `<div class="crt-subcat-group" data-subcat-idx="${si}">`;
|
||||||
eh += `<div class="crt-subcat-heading">${esc(subName)} <span class="crt-subcat-count">${sub.entries.length}</span></div>`;
|
eh += `<div class="crt-subcat-heading" data-subcat-toggle="${si}"><span class="crt-subcat-arrow">▸</span> ${esc(subName)} <span class="crt-subcat-count">${sub.entries.length}</span></div>`;
|
||||||
|
eh += `<div class="crt-subcat-entries" data-subcat-body="${si}" style="display:none">`;
|
||||||
for (const entry of sub.entries) eh += renderEntry(entry);
|
for (const entry of sub.entries) eh += renderEntry(entry);
|
||||||
eh += `</div>`;
|
eh += `</div>`;
|
||||||
|
eh += `</div>`;
|
||||||
}
|
}
|
||||||
entriesEl.innerHTML = eh;
|
entriesEl.innerHTML = eh;
|
||||||
|
|
||||||
|
// Bind subcategory toggle clicks
|
||||||
|
entriesEl.querySelectorAll('.crt-subcat-heading').forEach(heading => {
|
||||||
|
heading.addEventListener('click', (ev) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
const toggleIdx = heading.dataset.subcatToggle;
|
||||||
|
const body = entriesEl.querySelector(`[data-subcat-body="${toggleIdx}"]`);
|
||||||
|
const arrow = heading.querySelector('.crt-subcat-arrow');
|
||||||
|
if (body.style.display === 'none') {
|
||||||
|
body.style.display = '';
|
||||||
|
if (arrow) arrow.textContent = '▾';
|
||||||
|
heading.classList.add('expanded');
|
||||||
|
} else {
|
||||||
|
body.style.display = 'none';
|
||||||
|
if (arrow) arrow.textContent = '▸';
|
||||||
|
heading.classList.remove('expanded');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
panel.style.display = '';
|
panel.style.display = '';
|
||||||
panel.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
panel.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||||
});
|
});
|
||||||
|
|
@ -320,7 +351,7 @@
|
||||||
try {
|
try {
|
||||||
const data = await api(`/${slug}`);
|
const data = await api(`/${slug}`);
|
||||||
renderSector(data);
|
renderSector(data);
|
||||||
history.pushState({ view: 'detail', slug }, '', `/recon?sector=${slug}`);
|
history.pushState({ view: 'detail', slug: slug }, '', `/recon?sector=${slug}`);
|
||||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
root.innerHTML = `<div class="crt-empty">SECTOR NOT FOUND // ${esc(e.message)}</div>`;
|
root.innerHTML = `<div class="crt-empty">SECTOR NOT FOUND // ${esc(e.message)}</div>`;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue