feat(layout): stick the title row too, and chain the sticky offsets
"All items · N items" scrolled away like the pager did. It now sticks at the scrollport top (padding-top/negative margin cancel .content's padding so nothing shows through the gap), and the three things below it offset by --hdr-h: batch bar, pagination, and the table header (--hdr-h + --pag-h). Both vars are measured on .content in renderEntries. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+13
-4
@@ -800,7 +800,15 @@ input[type="range"]::-webkit-slider-thumb {
|
||||
.dropdown-item svg { color: var(--text-dim); }
|
||||
|
||||
.content { flex: 1; padding: 24px 32px; overflow-y: auto; }
|
||||
.content-header { display: flex; align-items: baseline; gap: 12px; margin-bottom: 20px; }
|
||||
/* Sticky title row. The negative top margin cancels .content's padding-top so
|
||||
nothing scrolls through the gap above it. Everything else that sticks
|
||||
(batch bar, pagination, table header) offsets by --hdr-h. */
|
||||
.content-header {
|
||||
display: flex; align-items: baseline; gap: 12px; margin-bottom: 20px;
|
||||
position: sticky; top: 0; z-index: 12;
|
||||
background: var(--bg);
|
||||
padding-top: 24px; margin-top: -24px;
|
||||
}
|
||||
.content-header h2 { font-size: 22px; font-weight: 600; margin: 0; }
|
||||
.content-meta { color: var(--text-faint); font-size: 12px; }
|
||||
|
||||
@@ -1000,7 +1008,7 @@ input[type="range"]::-webkit-slider-thumb {
|
||||
/* Batch action bar (appears when selection is non-empty) */
|
||||
.batch-bar {
|
||||
position: sticky;
|
||||
top: -1px;
|
||||
top: var(--hdr-h, 0px);
|
||||
z-index: 10;
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
padding: 10px 14px;
|
||||
@@ -2581,6 +2589,7 @@ body[data-editor-position="center"]:has(#settingsPanel.is-open)::before {
|
||||
.nav-item { justify-content: center; padding: 8px; }
|
||||
.topbar { padding: 12px 16px; }
|
||||
.content { padding: 16px; }
|
||||
.content-header { padding-top: 16px; margin-top: -16px; }
|
||||
.slideover { width: 100%; }
|
||||
/* On a narrow viewport the slideover fills the screen — no point
|
||||
pushing the shell, the table isn't visible anyway. */
|
||||
@@ -2676,7 +2685,7 @@ body[data-editor-position="center"]:has(#settingsPanel.is-open)::before {
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: var(--bg-elev);
|
||||
user-select: none;
|
||||
position: sticky; top: var(--pag-h, 0px);
|
||||
position: sticky; top: calc(var(--hdr-h, 0px) + var(--pag-h, 0px));
|
||||
z-index: 1;
|
||||
}
|
||||
.entry-table th.is-sortable { cursor: pointer; }
|
||||
@@ -2968,7 +2977,7 @@ input[type="password"]::-ms-clear {
|
||||
is pushed down by --pag-h (measured in renderEntries). */
|
||||
.pagination {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
top: var(--hdr-h, 0px);
|
||||
z-index: 2;
|
||||
background: var(--bg);
|
||||
display: flex; align-items: center; gap: 6px;
|
||||
|
||||
@@ -2296,13 +2296,16 @@ function renderGrid() {
|
||||
const start = (state.currentPage - 1) * state.pageSize;
|
||||
const pageList = list.slice(start, start + state.pageSize);
|
||||
|
||||
// Sticky offsets: the pagination bar parks under the title row, and the
|
||||
// table header under both. Measured, so a wrapped pager still lines up.
|
||||
const content = $('.content');
|
||||
content.style.setProperty('--hdr-h', $('.content-header').offsetHeight + 'px');
|
||||
if (total > 10) {
|
||||
const pag = renderPagination(total, totalPages);
|
||||
grid.appendChild(pag);
|
||||
// The table header sticks below the sticky pagination bar, not under it.
|
||||
grid.style.setProperty('--pag-h', pag.offsetHeight + 'px');
|
||||
content.style.setProperty('--pag-h', pag.offsetHeight + 'px');
|
||||
} else {
|
||||
grid.style.setProperty('--pag-h', '0px');
|
||||
content.style.setProperty('--pag-h', '0px');
|
||||
}
|
||||
|
||||
if (state.viewMode === 'table') {
|
||||
|
||||
Reference in New Issue
Block a user