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. */
|
/* 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 {
|
.cols-menu {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(100% + 4px);
|
top: calc(100% + 4px);
|
||||||
|
|||||||
@@ -286,12 +286,6 @@
|
|||||||
<svg><use href="#i-table"/></svg>
|
<svg><use href="#i-table"/></svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</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">
|
<div class="filters-wrap">
|
||||||
<button class="icon-btn" id="filtersBtn" title="Filters">
|
<button class="icon-btn" id="filtersBtn" title="Filters">
|
||||||
<svg><use href="#i-list"/></svg>
|
<svg><use href="#i-list"/></svg>
|
||||||
|
|||||||
@@ -3076,10 +3076,25 @@ function renderTableColsMenu() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyColsWrapVisibility() {
|
// Build the show/hide-columns picker (button + menu) for the table header
|
||||||
const wrap = document.getElementById('colsWrap');
|
// corner. Recreated on every renderTable; handlers are inline so they don't
|
||||||
if (!wrap) return;
|
// depend on once-wired listeners on a now-gone static toolbar node. The menu
|
||||||
wrap.style.display = (state.viewMode === 'table') ? '' : 'none';
|
// 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) {
|
function renderPagination(total, totalPages) {
|
||||||
@@ -3225,6 +3240,9 @@ function renderTable(list) {
|
|||||||
} else {
|
} else {
|
||||||
th.appendChild(el('span', null, col.label));
|
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);
|
headerRow.appendChild(th);
|
||||||
});
|
});
|
||||||
thead.appendChild(headerRow);
|
thead.appendChild(headerRow);
|
||||||
@@ -6803,13 +6821,13 @@ async function loadServerSettings() {
|
|||||||
// Apply visual settings immediately.
|
// Apply visual settings immediately.
|
||||||
if (remote.theme) setTheme(remote.theme);
|
if (remote.theme) setTheme(remote.theme);
|
||||||
if ('sidebarCollapsed' in remote) applySidebarCollapsed();
|
if ('sidebarCollapsed' in remote) applySidebarCollapsed();
|
||||||
// viewMode's active-button highlight + column-picker visibility were
|
// viewMode's active-button highlight was set once at init from the
|
||||||
// set once at init from the (port-wiped) localStorage default 'cards';
|
// (port-wiped) localStorage default 'cards'; re-sync it to the server
|
||||||
// re-sync them to the server value so the toolbar matches the content.
|
// 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) {
|
if ('viewMode' in remote) {
|
||||||
$$('.view-btn').forEach(b =>
|
$$('.view-btn').forEach(b =>
|
||||||
b.classList.toggle('is-active', b.dataset.view === state.viewMode));
|
b.classList.toggle('is-active', b.dataset.view === state.viewMode));
|
||||||
applyColsWrapVisibility();
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Network/server hiccup is harmless — localStorage cache still works.
|
// Network/server hiccup is harmless — localStorage cache still works.
|
||||||
@@ -6988,7 +7006,6 @@ async function init() {
|
|||||||
// Top-bar
|
// Top-bar
|
||||||
function applyViewMode() {
|
function applyViewMode() {
|
||||||
$$('.view-btn').forEach(b => b.classList.toggle('is-active', b.dataset.view === state.viewMode));
|
$$('.view-btn').forEach(b => b.classList.toggle('is-active', b.dataset.view === state.viewMode));
|
||||||
applyColsWrapVisibility();
|
|
||||||
renderGrid();
|
renderGrid();
|
||||||
}
|
}
|
||||||
applyViewMode();
|
applyViewMode();
|
||||||
@@ -7000,22 +7017,15 @@ async function init() {
|
|||||||
saveServerSettings();
|
saveServerSettings();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Show/hide table column picker. Built lazily on first open so the
|
// The column picker (button + menu) is rebuilt inside the table header by
|
||||||
// checkbox state always reflects the current `state.tableColsHidden`.
|
// buildColsPicker() with its own click handler. Here we only need the
|
||||||
const colsBtn = document.getElementById('colsBtn');
|
// outside-click close, queried live (the menu node changes each render).
|
||||||
const colsMenu = document.getElementById('colsMenu');
|
document.addEventListener('click', e => {
|
||||||
if (colsBtn && colsMenu) {
|
if (!e.target.closest('#colsWrap')) {
|
||||||
colsBtn.addEventListener('click', ev => {
|
const m = document.getElementById('colsMenu');
|
||||||
ev.stopPropagation();
|
if (m) m.classList.add('is-hidden');
|
||||||
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');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#themeBtn').addEventListener('click', () => {
|
$('#themeBtn').addEventListener('click', () => {
|
||||||
toggleTheme();
|
toggleTheme();
|
||||||
|
|||||||
Reference in New Issue
Block a user