Custom View: native sticky header, one-line Excel-style header; fixes

- Custom View header now uses the browser's sticky positioning like the
  other tables, so it no longer lags or bounces while scrolling. Because a
  sideways-scrolling box prevents sticky headers, the table is clipped and
  shifted sideways by a scrollbar pinned to the bottom of the window
  (shown only when the columns are wider than the page; trackpad,
  shift+wheel and touch swipes drive it too)
- Custom View header on one line like the other tables: drag grip, name,
  the combined sort/filter dropdown and copy icon (remove on hover)
- Workbench stack text boxes size to their contents on load and when the
  page is shown, not only while typing
- Demo sandbox waits for the worker's first sweep after a container
  restart instead of treating every device as unknown
This commit is contained in:
Johan Sandoval committed 2026-10-06 17:48:54 +00:00
1 parent b216ce43f2
commit 318c59e610
4 files changed
+114 -31

No files matched your search

+5 -9
View File
@@ -199,23 +199,19 @@
const active = activeFilters(ad, cols);
const activeKeys = new Set(active.map(c => ad.colKey(c.idx)));
// Header buttons (Custom View has its own filter icon, rerouted to our menu)
if (ad.custom) {
cols.forEach(c => {
const icon = c.th.querySelector('.col-filter-btn');
if (icon) icon.classList.toggle('xf-on', activeKeys.has(ad.colKey(c.idx)));
});
} else {
// Header buttons (Custom View's goes in its icon group, replacing its filter + sort icons)
{
cols.forEach(c => {
if (!c.filterable && !c.sortable) return;
let btn = c.th.querySelector(':scope > .xf-btn');
const holder = ad.custom ? (c.th.querySelector('.th-icons') || c.th) : c.th;
let btn = holder.querySelector(':scope > .xf-btn');
if (!btn) {
btn = document.createElement('button');
btn.type = 'button';
btn.className = 'xf-btn no-copy';
btn.title = 'Sort and filter';
btn.addEventListener('click', e => { e.stopPropagation(); openMenu(table, c.idx, btn); });
c.th.appendChild(btn);
holder.appendChild(btn);
}
// Like Excel's button: funnel when filtered, an arrow when sorted, otherwise a caret
const on = activeKeys.has(ad.colKey(c.idx));