Video Discover: sticky 'jump to section' nav for the deep rail stack
The page is now a long stack of rail groups (For you / Top 10 / New / Trending / Mood / Studios / Genres / More). A sticky chip bar lets you jump straight to any section — Netflix/Disney-style category nav. Chips stay in lockstep with the groups: async-only groups (foryou/collection/ taste) reveal their chip when filled; pruned groups hide theirs. Lives inside the shelves host so it auto-hides in the Browse-all grid view.
This commit is contained in:
parent
a275cbfb7a
commit
24b79dc29e
2 changed files with 54 additions and 4 deletions
|
|
@ -543,7 +543,18 @@
|
|||
}
|
||||
function renderShelves() {
|
||||
var host = $('[data-vdsc-shelves]'); if (!host) return;
|
||||
host.innerHTML = buildSections().map(function (sec) {
|
||||
var sections = buildSections();
|
||||
// A sticky "jump to section" bar (Netflix/Disney pattern) — the page is a deep
|
||||
// stack of rails, so quick navigation makes it far easier to browse. Chips for
|
||||
// async-only groups (foryou/collection/taste) start hidden, revealed when filled;
|
||||
// chips for groups that prune away hide in lockstep (see reveal/pruneGroup).
|
||||
var nav = '<nav class="vdsc-jumpnav" data-vdsc-jumpnav aria-label="Jump to section">' +
|
||||
sections.map(function (sec) {
|
||||
var hideCls = sec.rails.length ? '' : ' hidden';
|
||||
return '<button class="vdsc-jump' + hideCls + '" type="button" data-jump="' +
|
||||
sec.id + '">' + esc(sec.label) + '</button>';
|
||||
}).join('') + '</nav>';
|
||||
host.innerHTML = nav + sections.map(function (sec) {
|
||||
var rails = sec.rails.map(lazyShelfHtml).join('');
|
||||
// Groups with no static rails (async-only, e.g. gaps) start hidden — revealed when filled.
|
||||
var emptyCls = sec.rails.length ? '' : ' vdsc-group--empty';
|
||||
|
|
@ -552,16 +563,35 @@
|
|||
'<div class="vdsc-group-body" data-group-body="' + sec.id + '">' + rails + '</div>' +
|
||||
'</section>';
|
||||
}).join('');
|
||||
wireJumpNav(host);
|
||||
observeShelves();
|
||||
}
|
||||
// Reveal a group's header once an async loader has put rails in it.
|
||||
// Smooth-scroll to a group when its jump chip is clicked (delegated, wired once).
|
||||
function wireJumpNav(host) {
|
||||
var nav = $('[data-vdsc-jumpnav]', host);
|
||||
if (!nav || nav.getAttribute('data-wired')) return;
|
||||
nav.setAttribute('data-wired', '1');
|
||||
nav.addEventListener('click', function (e) {
|
||||
var btn = e.target.closest('[data-jump]'); if (!btn) return;
|
||||
var g = $('[data-group="' + btn.getAttribute('data-jump') + '"]');
|
||||
if (g) { try { g.scrollIntoView({ behavior: 'smooth', block: 'start' }); } catch (x) { g.scrollIntoView(); } }
|
||||
});
|
||||
}
|
||||
// Reveal a group's header once an async loader has put rails in it (+ its jump chip).
|
||||
function revealGroup(id) {
|
||||
var g = $('[data-group="' + id + '"]');
|
||||
if (g) g.classList.remove('vdsc-group--empty');
|
||||
var chip = $('[data-jump="' + id + '"]');
|
||||
if (chip) chip.classList.remove('hidden');
|
||||
}
|
||||
// Hide a group whose body has no shelves left (every rail failed / returned nothing).
|
||||
// Hide a group whose body has no shelves left (every rail failed / returned nothing) + its chip.
|
||||
function pruneGroup(g) {
|
||||
if (g && !g.querySelector('.vdsc-shelf')) g.classList.add('vdsc-group--empty');
|
||||
if (g && !g.querySelector('.vdsc-shelf')) {
|
||||
g.classList.add('vdsc-group--empty');
|
||||
var id = g.getAttribute('data-group');
|
||||
var chip = id && $('[data-jump="' + id + '"]');
|
||||
if (chip) chip.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
function observeShelves() {
|
||||
if (state.io) state.io.disconnect();
|
||||
|
|
|
|||
|
|
@ -2303,6 +2303,26 @@ body[data-side="video"] #soulsync-toggle { display: none; }
|
|||
A group with no rails (async-only, not yet filled, or all rails dropped) is hidden entirely. */
|
||||
.vdsc-group { margin: 0; }
|
||||
.vdsc-group--empty { display: none; }
|
||||
|
||||
/* ── sticky 'jump to section' bar — quick nav across the deep rail stack ──────── */
|
||||
.vdsc-jumpnav {
|
||||
position: sticky; top: 0; z-index: 6;
|
||||
display: flex; gap: 8px; flex-wrap: nowrap; overflow-x: auto;
|
||||
margin: 0 0 6px; padding: 11px 2px;
|
||||
background: linear-gradient(180deg, rgba(10, 11, 16, 0.94) 35%, rgba(10, 11, 16, 0.55) 80%, transparent);
|
||||
-webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.vdsc-jumpnav::-webkit-scrollbar { display: none; }
|
||||
.vdsc-jump {
|
||||
flex: 0 0 auto; padding: 7px 15px; border-radius: 999px; cursor: pointer;
|
||||
border: 1px solid rgba(255, 255, 255, 0.12); background: rgba(255, 255, 255, 0.05);
|
||||
color: rgba(255, 255, 255, 0.78); font-size: 12.5px; font-weight: 700; white-space: nowrap;
|
||||
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
.vdsc-jump:hover { background: rgba(var(--accent-rgb, 88 101 242), 0.85); border-color: transparent; color: #fff; }
|
||||
.vdsc-jump.hidden { display: none; }
|
||||
|
||||
.vdsc-group-head { font-size: 12.5px; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase;
|
||||
color: rgba(255, 255, 255, 0.5); margin: 30px 0 16px; padding-bottom: 9px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.07); }
|
||||
|
|
|
|||
Loading…
Reference in a new issue