feat(web): scroll-row arrows + stable desktop media tile
Home rows get hover left/right arrows that only show for the scrollable direction (enhanceScrollRow + initScrollRows, called from startApp); visibility recomputed on scroll/resize/content-load. Fix the OS media tile flicker when skipping on desktop PWA: mutate the existing MediaMetadata in place instead of assigning a new one each track (the replacement made Windows tear down and rebuild the tile). Action handlers are now set once. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
7498e45b16
commit
d65fbcd11e
5 files changed
+98
-9
No files matched your search
@@ -103,3 +103,55 @@ export function mkSection(title) {
|
||||
d.innerHTML = `<div class="search-section-title">${title}</div>`;
|
||||
return d;
|
||||
}
|
||||
|
||||
// ─── HORIZONTAL SCROLL-ROW ARROWS (desktop) ───
|
||||
const _CHEV_L = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>';
|
||||
const _CHEV_R = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>';
|
||||
|
||||
/** Wrap a `.scroll-row` with left/right arrows that appear only for the scrollable direction. */
|
||||
export function enhanceScrollRow(row) {
|
||||
if (!row || row.dataset.saEnhanced) return;
|
||||
row.dataset.saEnhanced = '1';
|
||||
|
||||
const wrap = document.createElement('div');
|
||||
wrap.className = 'scroll-row-wrap';
|
||||
row.parentNode.insertBefore(wrap, row);
|
||||
wrap.appendChild(row);
|
||||
|
||||
const mkBtn = (cls, html, label) => {
|
||||
const b = document.createElement('button');
|
||||
b.type = 'button';
|
||||
b.className = 'scroll-arrow ' + cls;
|
||||
b.setAttribute('aria-label', label);
|
||||
b.innerHTML = html;
|
||||
wrap.appendChild(b);
|
||||
return b;
|
||||
};
|
||||
const left = mkBtn('sa-left', _CHEV_L, 'Zurück');
|
||||
const right = mkBtn('sa-right', _CHEV_R, 'Weiter');
|
||||
|
||||
const EPS = 4;
|
||||
const update = () => {
|
||||
left.classList.toggle('can-scroll', row.scrollLeft > EPS);
|
||||
right.classList.toggle('can-scroll', row.scrollLeft < row.scrollWidth - row.clientWidth - EPS);
|
||||
// Vertically center the arrows on the cover art (fallback: CSS default 72px)
|
||||
const art = row.querySelector('.card-art') || row.querySelector('.card');
|
||||
if (art) {
|
||||
const top = art.getBoundingClientRect().top - wrap.getBoundingClientRect().top + art.offsetHeight / 2;
|
||||
if (top > 0) { left.style.top = right.style.top = top + 'px'; }
|
||||
}
|
||||
};
|
||||
const step = () => Math.max(160, row.clientWidth * 0.8);
|
||||
left.addEventListener('click', () => row.scrollBy({ left: -step(), behavior: 'smooth' }));
|
||||
right.addEventListener('click', () => row.scrollBy({ left: step(), behavior: 'smooth' }));
|
||||
|
||||
row.addEventListener('scroll', update, { passive: true });
|
||||
new ResizeObserver(update).observe(row);
|
||||
new MutationObserver(update).observe(row, { childList: true });
|
||||
update();
|
||||
}
|
||||
|
||||
/** Enhance every `.scroll-row` currently in the DOM (the static Home rows). */
|
||||
export function initScrollRows() {
|
||||
document.querySelectorAll('.scroll-row').forEach(enhanceScrollRow);
|
||||
}
|
||||
Reference in new issue
Block a user