Skip to content

Commit caec00e

Browse files
authored
synq: add collapsible groups to version selector (#47)
## Motivation After #44 fixed tag discovery, the version dropdown now lists all 49 patch releases in a flat list, making it unusably long. ## Changes - Group versions by minor release (e.g. "0.2.x") with collapsible sections - Clicking a group label navigates to the latest patch in that group - Clicking the chevron expands to show individual patch versions - Menu is now scrollable (max-height: 70vh)
1 parent 0860015 commit caec00e

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed

web/docs/static/style.css

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,9 @@ header nav ul a:hover { color: var(--c-fg); }
317317
position: absolute;
318318
top: calc(100% + 4px);
319319
left: 0;
320-
min-width: 120px;
320+
min-width: 140px;
321+
max-height: 70vh;
322+
overflow-y: auto;
321323
background: var(--c-surface);
322324
border: 1px solid var(--c-border);
323325
border-radius: var(--radius);
@@ -340,6 +342,34 @@ header nav ul a:hover { color: var(--c-fg); }
340342
.version-switcher__menu a:hover { color: var(--c-fg); background: var(--c-bg); }
341343
.version-switcher__menu a.active { color: var(--c-accent); font-weight: 500; }
342344

345+
.version-switcher__group-label {
346+
display: flex;
347+
align-items: center;
348+
justify-content: space-between;
349+
padding: 0.35rem var(--sp-md);
350+
font-size: var(--text-sm);
351+
color: var(--c-muted);
352+
cursor: pointer;
353+
user-select: none;
354+
border-top: 1px solid var(--c-border);
355+
margin-top: var(--sp-xs);
356+
}
357+
358+
.version-switcher__group-label:first-child { border-top: none; margin-top: 0; }
359+
.version-switcher__group-label:hover { color: var(--c-fg); background: var(--c-bg); }
360+
361+
.version-switcher__group-label svg {
362+
transition: transform 0.15s;
363+
}
364+
365+
.version-switcher__group-label.expanded svg {
366+
transform: rotate(180deg);
367+
}
368+
369+
.version-switcher__group { display: none; }
370+
.version-switcher__group.expanded { display: block; }
371+
.version-switcher__group a { padding-left: calc(var(--sp-md) + 0.5rem); }
372+
343373
/* Theme toggle */
344374
[data-theme="dark"] .icon-sun { display: block; }
345375
[data-theme="dark"] .icon-moon { display: none; }

web/docs/templates/base.html

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,59 @@
113113
.then(function(r) { return r.json(); })
114114
.then(function(versions) {
115115
menu.innerHTML = '';
116+
// "main" and latest always shown directly
117+
var topLevel = [];
118+
var groups = {};
119+
var groupOrder = [];
116120
versions.forEach(function(v) {
121+
if (v.version === 'main' || v.label.indexOf('(latest)') !== -1) {
122+
topLevel.push(v);
123+
return;
124+
}
125+
// Group by major.minor (e.g. "0.2" from "v0.2.14")
126+
var m = v.version.match(/^v?(\d+\.\d+)\./);
127+
var key = m ? m[1] : 'other';
128+
if (!groups[key]) { groups[key] = []; groupOrder.push(key); }
129+
groups[key].push(v);
130+
});
131+
// Render top-level entries
132+
topLevel.forEach(function(v) {
117133
var a = document.createElement('a');
118134
a.href = '/' + v.version + pagePath;
119135
a.textContent = v.label;
120136
if (v.version === current) a.classList.add('active');
121137
menu.appendChild(a);
122138
});
139+
// Render collapsible groups
140+
var chevron = '<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"/></svg>';
141+
groupOrder.forEach(function(key) {
142+
var items = groups[key];
143+
var hasActive = items.some(function(v) { return v.version === current; });
144+
// Group label navigates to the latest (first) in the group
145+
var lbl = document.createElement('a');
146+
lbl.href = '/' + items[0].version + pagePath;
147+
lbl.className = 'version-switcher__group-label' + (hasActive ? ' expanded' : '');
148+
lbl.innerHTML = key + '.x ' + chevron;
149+
// Chevron toggles expansion without navigating
150+
var toggle = lbl.querySelector('svg');
151+
toggle.addEventListener('click', function(e) {
152+
e.preventDefault();
153+
e.stopPropagation();
154+
lbl.classList.toggle('expanded');
155+
grp.classList.toggle('expanded');
156+
});
157+
var grp = document.createElement('div');
158+
grp.className = 'version-switcher__group' + (hasActive ? ' expanded' : '');
159+
items.forEach(function(v) {
160+
var a = document.createElement('a');
161+
a.href = '/' + v.version + pagePath;
162+
a.textContent = v.label;
163+
if (v.version === current) a.classList.add('active');
164+
grp.appendChild(a);
165+
});
166+
menu.appendChild(lbl);
167+
menu.appendChild(grp);
168+
});
123169
})
124170
.catch(function() {});
125171
})();

0 commit comments

Comments
 (0)