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:
@@ -1933,6 +1933,11 @@ input[type="range"]::-webkit-slider-thumb {
|
||||
}
|
||||
|
||||
/* Table column picker dropdown — only rendered in table view. */
|
||||
.cols-wrap {
|
||||
position: relative; /* anchor for the absolutely-positioned menu */
|
||||
display: inline-flex;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.cols-menu {
|
||||
position: absolute;
|
||||
top: calc(100% + 4px);
|
||||
|
||||
@@ -286,12 +286,6 @@
|
||||
<svg><use href="#i-table"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="cols-wrap" id="colsWrap" style="display:none;position:relative">
|
||||
<button class="icon-btn" id="colsBtn" title="Show / hide columns">
|
||||
<svg><use href="#i-settings"/></svg>
|
||||
</button>
|
||||
<div class="cols-menu is-hidden" id="colsMenu"></div>
|
||||
</div>
|
||||
<div class="filters-wrap">
|
||||
<button class="icon-btn" id="filtersBtn" title="Filters">
|
||||
<svg><use href="#i-list"/></svg>
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user