Deck builder: sticky section bar for jumping between sections
A bar below the toolbar pins under the top bar and jumps between the card sections (Available / In other decks / Not owned, To pull / In deck, or All cards, plus Maybeboard), marking the one in view. Where it fits it shows inline tabs; on a narrow bar, one button names the current section and opens a menu of them all, so nothing scrolls sideways. The switch follows the bar's own width via a container query. It also holds the deck filter and an up button back to the overview. Group headers and column headers pin below the bar. Closes #23 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
116
src/styles.css
116
src/styles.css
@@ -779,6 +779,7 @@ input[type="checkbox"] {
|
||||
scrolled-past rows still show. */
|
||||
--content-pad-top: var(--space-5);
|
||||
--group-header-h: 40px;
|
||||
--section-nav-h: 48px;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding: var(--content-pad-top) var(--space-6);
|
||||
@@ -965,7 +966,7 @@ h4 {
|
||||
* tag) since h3 is also used for .dialog-title, which must not be sticky. */
|
||||
.group-header {
|
||||
position: sticky;
|
||||
top: calc(-1 * var(--content-pad-top, 0px));
|
||||
top: calc(var(--sticky-offset, 0px) - var(--content-pad-top, 0px));
|
||||
z-index: 5;
|
||||
margin: var(--space-4) 0 var(--space-2);
|
||||
/* A fixed height, so a grouped table's column headers can pin just below
|
||||
@@ -1582,7 +1583,7 @@ th {
|
||||
letter-spacing: var(--tracking-label);
|
||||
color: var(--muted);
|
||||
position: sticky;
|
||||
top: calc(-1 * var(--content-pad-top, 0px));
|
||||
top: calc(var(--sticky-offset, 0px) - var(--content-pad-top, 0px));
|
||||
background: var(--bg-content);
|
||||
border-bottom: 1px solid var(--border);
|
||||
z-index: 1;
|
||||
@@ -1594,7 +1595,7 @@ td {
|
||||
}
|
||||
/* Under a sticky group header, pin below it instead of behind it. */
|
||||
.group-header + table th {
|
||||
top: calc(var(--group-header-h) - var(--content-pad-top, 0px));
|
||||
top: calc(var(--sticky-offset, 0px) + var(--group-header-h) - var(--content-pad-top, 0px));
|
||||
}
|
||||
tbody tr {
|
||||
transition: background 0.08s;
|
||||
@@ -3139,6 +3140,115 @@ button.pull-action {
|
||||
margin: 4px 0 18px;
|
||||
}
|
||||
|
||||
/* Section bar (see `SectionNav`): pins under the top bar, so group headers
|
||||
and column headers below it pin under it in turn via --sticky-offset. */
|
||||
.deck-builder {
|
||||
--sticky-offset: var(--section-nav-h);
|
||||
}
|
||||
.deck-section {
|
||||
scroll-margin-top: calc(var(--section-nav-h) + var(--space-2));
|
||||
}
|
||||
.section-nav {
|
||||
position: sticky;
|
||||
top: calc(-1 * var(--content-pad-top, 0px));
|
||||
z-index: 6;
|
||||
height: var(--section-nav-h);
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
margin-top: var(--space-3);
|
||||
background: var(--bg-content);
|
||||
border-bottom: 1px solid var(--border-soft);
|
||||
/* Tabs or jump menu is decided by the bar's own width (the nav rail eats
|
||||
into the window). Not on .deck-builder: containment there would trap
|
||||
its inline position: fixed dialogs. */
|
||||
container-type: inline-size;
|
||||
}
|
||||
.section-nav button {
|
||||
font-size: 13px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* The bar's own buttons (not the jump menu's items) share one height. */
|
||||
.section-nav > button,
|
||||
.section-nav-tabs button,
|
||||
.section-nav-jump > button {
|
||||
height: 32px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
.section-nav .section-nav-top {
|
||||
flex-shrink: 0;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
padding: 0;
|
||||
}
|
||||
.section-nav-top svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
.section-nav-tabs {
|
||||
display: flex;
|
||||
gap: var(--space-1);
|
||||
min-width: 0;
|
||||
}
|
||||
.section-nav-tabs button {
|
||||
background: transparent;
|
||||
border-color: transparent;
|
||||
color: var(--muted);
|
||||
}
|
||||
.section-nav-tabs button:hover {
|
||||
background: var(--bg-hover);
|
||||
color: var(--text);
|
||||
}
|
||||
.section-nav-tabs button.active {
|
||||
background: var(--accent-subtle);
|
||||
border-color: var(--accent-glow);
|
||||
color: var(--text-strong);
|
||||
}
|
||||
.section-nav-tabs button.empty:not(.active) {
|
||||
color: var(--faint);
|
||||
}
|
||||
.section-nav-jump {
|
||||
position: relative;
|
||||
display: none;
|
||||
min-width: 0;
|
||||
max-width: 50%;
|
||||
}
|
||||
.section-nav-jump > button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
max-width: 100%;
|
||||
}
|
||||
.section-nav-jump-label {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.section-nav-menu {
|
||||
min-width: 220px;
|
||||
}
|
||||
.section-nav-filter {
|
||||
height: 32px;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
margin-left: auto;
|
||||
min-width: 140px;
|
||||
max-width: 240px;
|
||||
}
|
||||
/* Below this the longest tab set (Available / In other decks / Not owned /
|
||||
Maybeboard, with counts) plus a minimum-width filter no longer fits. */
|
||||
@container (max-width: 740px) {
|
||||
.section-nav-tabs {
|
||||
display: none;
|
||||
}
|
||||
.section-nav-jump {
|
||||
display: block;
|
||||
}
|
||||
.section-nav-filter {
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* The four top-of-page info panels (commander, meta, analysis, legality).
|
||||
Single column matches the existing top-to-bottom reading order on
|
||||
narrow/portrait viewports; on wide viewports the compact panels move
|
||||
|
||||
Reference in New Issue
Block a user