style(table): move the column picker into the table header corner

The show/hide-columns gear only makes sense in table view but sat in the
global toolbar (needing applyColsWrapVisibility to hide it elsewhere). Build
it inside the actions-column header cell in renderTable instead, with inline
handlers (recreated each render, so no dependence on once-wired listeners on
a static node). Removed #colsWrap from the toolbar + the now-obsolete
applyColsWrapVisibility and its callers; kept the menu id so
renderTableColsMenu still populates it, and a live-queried outside-click close.
Added .cols-wrap CSS (was an inline position:relative on the old node).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
r-zakarya
2026-07-21 20:00:56 +01:00
parent 0d40328a24
commit 4dfd908a9a
3 changed files with 40 additions and 31 deletions
+35 -25
View File
@@ -3076,10 +3076,25 @@ function renderTableColsMenu() {
});
}
function applyColsWrapVisibility() {
const wrap = document.getElementById('colsWrap');
if (!wrap) return;
wrap.style.display = (state.viewMode === 'table') ? '' : 'none';
// Build the show/hide-columns picker (button + menu) for the table header
// corner. Recreated on every renderTable; handlers are inline so they don't
// depend on once-wired listeners on a now-gone static toolbar node. The menu
// keeps id="colsMenu" so renderTableColsMenu (which queries it) still works.
function buildColsPicker() {
const wrap = el('div', { class: 'cols-wrap', id: 'colsWrap' });
const menu = el('div', { class: 'cols-menu is-hidden', id: 'colsMenu' });
const btn = el('button', {
class: 'icon-btn', type: 'button', title: 'Show / hide columns',
on: { click: ev => {
ev.stopPropagation();
if (menu.classList.contains('is-hidden')) renderTableColsMenu();
menu.classList.toggle('is-hidden');
} },
});
btn.appendChild(icon('i-settings'));
wrap.appendChild(btn);
wrap.appendChild(menu);
return wrap;
}
function renderPagination(total, totalPages) {
@@ -3225,6 +3240,9 @@ function renderTable(list) {
} else {
th.appendChild(el('span', null, col.label));
}
// Column picker lives in the table's own header corner (it only makes
// sense in table view), not the global toolbar.
if (col.key === 'actions') th.appendChild(buildColsPicker());
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
@@ -6803,13 +6821,13 @@ async function loadServerSettings() {
// Apply visual settings immediately.
if (remote.theme) setTheme(remote.theme);
if ('sidebarCollapsed' in remote) applySidebarCollapsed();
// viewMode's active-button highlight + column-picker visibility were
// set once at init from the (port-wiped) localStorage default 'cards';
// re-sync them to the server value so the toolbar matches the content.
// viewMode's active-button highlight was set once at init from the
// (port-wiped) localStorage default 'cards'; re-sync it to the server
// value so the toolbar matches the content. (The column picker now
// lives in the table header, so no separate visibility toggle.)
if ('viewMode' in remote) {
$$('.view-btn').forEach(b =>
b.classList.toggle('is-active', b.dataset.view === state.viewMode));
applyColsWrapVisibility();
}
} catch (e) {
// Network/server hiccup is harmless — localStorage cache still works.
@@ -6988,7 +7006,6 @@ async function init() {
// Top-bar
function applyViewMode() {
$$('.view-btn').forEach(b => b.classList.toggle('is-active', b.dataset.view === state.viewMode));
applyColsWrapVisibility();
renderGrid();
}
applyViewMode();
@@ -7000,22 +7017,15 @@ async function init() {
saveServerSettings();
}));
// Show/hide table column picker. Built lazily on first open so the
// checkbox state always reflects the current `state.tableColsHidden`.
const colsBtn = document.getElementById('colsBtn');
const colsMenu = document.getElementById('colsMenu');
if (colsBtn && colsMenu) {
colsBtn.addEventListener('click', ev => {
ev.stopPropagation();
const isHidden = colsMenu.classList.contains('is-hidden');
if (isHidden) renderTableColsMenu();
colsMenu.classList.toggle('is-hidden');
});
document.addEventListener('click', e => {
if (!e.target.closest('#colsWrap'))
colsMenu.classList.add('is-hidden');
});
}
// The column picker (button + menu) is rebuilt inside the table header by
// buildColsPicker() with its own click handler. Here we only need the
// outside-click close, queried live (the menu node changes each render).
document.addEventListener('click', e => {
if (!e.target.closest('#colsWrap')) {
const m = document.getElementById('colsMenu');
if (m) m.classList.add('is-hidden');
}
});
$('#themeBtn').addEventListener('click', () => {
toggleTheme();