Unify tables and listings

This commit is contained in:
2026-05-27 20:09:52 +02:00
parent e089e0b2c3
commit 20a6bac3d6
5 changed files with 91 additions and 76 deletions
+31 -21
View File
@@ -70,6 +70,15 @@
dropdown.className = 'suggest-dropdown';
host.appendChild(dropdown);
function makeRow(cls, tabbable) {
var tr = document.createElement('tr');
tr.className = cls;
if (tabbable) tr.setAttribute('tabindex', '0');
var td = document.createElement('td');
tr.appendChild(td);
return { tr: tr, td: td };
}
var state = {
results: [],
total: 0,
@@ -102,49 +111,50 @@
dropdown.classList.remove('is-open');
return;
}
var table = document.createElement('table');
table.className = 'data-table';
var tbody = document.createElement('tbody');
table.appendChild(tbody);
var tokens = tokenize(state.query);
if (state.results.length === 0) {
var empty = document.createElement('div');
empty.className = 'suggest-row is-empty';
empty.textContent = 'No matches';
dropdown.appendChild(empty);
var empty = makeRow('is-empty', false);
empty.td.textContent = 'No matches';
tbody.appendChild(empty.tr);
} else {
state.results.forEach(function (r, i) {
var row = document.createElement('button');
row.type = 'button';
row.className = 'suggest-row';
row.setAttribute('data-idx', String(i));
var row = makeRow('suggest-row', true);
row.tr.setAttribute('data-idx', String(i));
var nameEl = document.createElement('span');
nameEl.className = 'suggest-name';
nameEl.innerHTML = highlight(r.name, tokens);
var pathEl = document.createElement('span');
pathEl.className = 'suggest-path';
pathEl.textContent = '/' + r.path;
row.appendChild(nameEl);
row.appendChild(pathEl);
if (i === state.activeIdx) row.classList.add('is-active');
row.addEventListener('mousedown', function (e) {
row.td.appendChild(nameEl);
row.td.appendChild(pathEl);
if (i === state.activeIdx) row.tr.classList.add('is-active');
row.tr.addEventListener('mousedown', function (e) {
// mousedown (not click) so the input doesn't blur-close
// the dropdown before the pick handler fires.
e.preventDefault();
pick(i);
});
dropdown.appendChild(row);
tbody.appendChild(row.tr);
});
if (opts.showFooter && state.total > state.results.length) {
var footer = document.createElement('button');
footer.type = 'button';
footer.className = 'suggest-row suggest-footer';
footer.textContent = 'Show all ' + state.total + ' matches';
var footer = makeRow('suggest-row suggest-footer', true);
footer.td.textContent = 'Show all ' + state.total + ' matches';
var footerIdx = state.results.length;
if (state.activeIdx === footerIdx) footer.classList.add('is-active');
footer.addEventListener('mousedown', function (e) {
if (state.activeIdx === footerIdx) footer.tr.classList.add('is-active');
footer.tr.addEventListener('mousedown', function (e) {
e.preventDefault();
pickFooter();
});
dropdown.appendChild(footer);
tbody.appendChild(footer.tr);
}
}
dropdown.appendChild(table);
dropdown.classList.add('is-open');
}
@@ -225,7 +235,7 @@
state.activeIdx = next;
render();
// Keep the active row in view.
var active = dropdown.querySelector('.suggest-row.is-active');
var active = dropdown.querySelector('tr.is-active');
if (active && active.scrollIntoView) {
try { active.scrollIntoView({ block: 'nearest' }); } catch (e) {}
}