From a57951c0383c446e944956937462064c43ee3251 Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Sat, 13 Jun 2026 19:57:22 -0700 Subject: [PATCH] video dashboard: header matches music (sweep hidden, video meta + quick-nav) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The video dashboard header now mirrors music's: icon + shimmer title, subtitle, the Watchlist/Wishlist quick-nav (top-right), and the action-button row. Differences, all isolated: - Sweep band kept in markup but hidden on the video side (no animation for now; meta-source-driven equivalent may return later). - Quick-nav reuses .watchlist-button/.wishlist-button styling but carries NO music IDs (no duplicate IDs, no music-JS binding) — navigates to the video Watchlist/Wishlist pages via data-video-goto. - header-actions holds disabled TMDB/TVDB/Trakt/OMDb placeholder chips (.video-meta-button) standing in for music's enrichment buttons until the video meta sources are wired. No inline onclick; 75 tests green. --- tests/test_video_side_shell.py | 26 ++++++++++++++++++++++++++ webui/index.html | 29 +++++++++++++++++++++++++++-- webui/static/video/video-side.css | 29 +++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/tests/test_video_side_shell.py b/tests/test_video_side_shell.py index dad466bd..66783f24 100644 --- a/tests/test_video_side_shell.py +++ b/tests/test_video_side_shell.py @@ -93,6 +93,32 @@ def test_video_dashboard_subpage_present_with_expected_cards(): assert "onclick" not in block +def test_video_dashboard_header_matches_music_shape(): + block = _block( + _INDEX, r'
") + header = _block(block, r'
', "
") + # Same shell as music: sweep band + icon title + subtitle. + assert "dashboard-header-sweep" in header + assert "page-header-icon" in header and "header-title" in header + assert "header-subtitle" in header + # Watchlist/Wishlist quick-nav present, navigating to the video pages (no + # music IDs — would duplicate + bind music JS — just classes + data-goto). + assert "header-quick-nav" in header + assert 'data-video-goto="video-watchlist"' in header + assert 'data-video-goto="video-wishlist"' in header + assert 'id="watchlist-button"' not in header and 'id="wishlist-button"' not in header + # Meta-source placeholder buttons stand in for music's enrichment row. + assert "header-actions" in header + for src in ("tmdb", "tvdb", "trakt", "omdb"): + assert f'data-video-meta="{src}"' in header + assert "onclick" not in header + + +def test_video_dashboard_sweep_hidden_on_video_side(): + css = _CSS_PATH.read_text(encoding="utf-8") + assert 'body[data-side="video"] .dashboard-header-sweep' in css + + def test_video_dashboard_has_placeholder_slot_for_unbuilt_pages(): assert 'id="video-placeholder-slot"' in _INDEX diff --git a/webui/index.html b/webui/index.html index d148b34d..78db64a0 100644 --- a/webui/index.html +++ b/webui/index.html @@ -425,11 +425,36 @@
-
+
-

Video Dashboard

+

Video Dashboard

Monitor your video library, downloads and services

+ +
+ + + + +
+ +
+ + +
diff --git a/webui/static/video/video-side.css b/webui/static/video/video-side.css index 103006bd..5ede3952 100644 --- a/webui/static/video/video-side.css +++ b/webui/static/video/video-side.css @@ -108,6 +108,35 @@ body[data-side="video"] .status-section { display: none; } +/* ── Dashboard header: match music, minus the sweep animation ──────────── */ +/* The header reuses music's .dashboard-header markup/CSS for an identical look; + we only mute the ambient sweep on the video side (equiv may return later, + driven by meta sources). Scoped to data-side="video" so music is untouched. */ +body[data-side="video"] .dashboard-header-sweep { + display: none; +} + +/* Video meta-source buttons — the placeholder equivalents of music's round + enrichment buttons. Disabled pills until the video meta sources are wired. */ +.video-meta-button { + height: 40px; + padding: 0 18px; + border-radius: 20px; + font-size: 13px; + font-weight: 600; + letter-spacing: 0.02em; + color: var(--text-secondary, #9aa0aa); + background: rgba(18, 18, 22, 0.85); + border: 1px solid rgba(255, 255, 255, 0.10); + backdrop-filter: blur(8px) saturate(1.2); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.06); + cursor: not-allowed; + opacity: 0.55; +} +.video-meta-button:disabled { + cursor: not-allowed; +} + /* ── Subpages: one built video page shown at a time ────────────────────── */ /* Each real page is a .video-subpage inside #video-page-host; the controller toggles the [hidden] attribute. Be explicit so no reused .dash-* rule can