feat: sidebar empty-state when no streamers added yet

First-launch (or after-clearing-everything) opens the app with an
empty sidebar streamer list — just the "Streamer" section heading
and a blank area below. New users had no in-app indication of where
to add their first streamer. The "Add streamer..." input lives in
the TOP bar, which is non-obvious from the sidebar context.

renderStreamers now short-circuits on empty streamers[] and stamps
a small dashed-border hint card into the list with locale-driven
copy pointing the user at the top-right input ("No streamers yet.
Add one via the input at the top right." / "Noch keine Streamer.
Fuege oben rechts einen hinzu.").

The empty state styling (.streamer-list-empty) is intentionally
subtler than the full-page .empty-state used for the VOD grid —
dashed border + tinted background + small padding so it fits the
narrow sidebar rail without dominating it.

Also clears the streamer-section-counter on this branch and hides
the bulk-remove X button, since both would otherwise have stale
state from a previous non-empty render.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
xRangerDE 2026-05-11 02:24:50 +02:00
parent a7c251f016
commit 6fdfa08ecb
4 changed files with 34 additions and 2 deletions

View File

@ -352,7 +352,8 @@ const UI_TEXT_DE = {
autoRecordScanTriggered: 'Manueller Scan: {count} Live-Aufnahme(n) gestartet.',
autoRecordScanEmpty: 'Manueller Scan: kein Streamer ist gerade live.',
liveNowTooltip: 'Aktuell live auf Twitch',
modalCloseAria: 'Dialog schliessen'
modalCloseAria: 'Dialog schliessen',
sidebarEmpty: 'Noch keine Streamer. Fuege oben rechts einen hinzu.'
},
vods: {
noneTitle: 'Keine VODs',

View File

@ -352,7 +352,8 @@ const UI_TEXT_EN = {
autoRecordScanTriggered: 'Manual scan: {count} live recording(s) started.',
autoRecordScanEmpty: 'Manual scan: no streamers currently live.',
liveNowTooltip: 'Currently live on Twitch',
modalCloseAria: 'Close dialog'
modalCloseAria: 'Close dialog',
sidebarEmpty: 'No streamers yet. Add one via the input at the top right.'
},
vods: {
noneTitle: 'No VODs',

View File

@ -426,6 +426,21 @@ function renderStreamers(): void {
// Compact title margin when filter is shown — avoids double gap.
if (sectionTitle) sectionTitle.style.marginBottom = showFilter ? '4px' : '';
// Empty state — small hint inside the sidebar when no streamers have
// been added yet. Without this the user sees a heading + blank space
// and has to guess where to add the first streamer.
if (all.length === 0) {
const empty = document.createElement('div');
empty.className = 'streamer-list-empty';
empty.textContent = UI_TEXT.streamers.sidebarEmpty || 'No streamers yet. Add one via the top bar.';
list.appendChild(empty);
const counter = document.getElementById('streamerSectionCounter');
if (counter) counter.textContent = '';
const bulkBtn = document.getElementById('btnStreamerBulkRemove') as HTMLButtonElement | null;
if (bulkBtn) bulkBtn.style.display = 'none';
return;
}
// Section counter — "X · Y live". Updates on every re-render, so it
// stays accurate after add/remove/live-status changes.
const counter = document.getElementById('streamerSectionCounter');

View File

@ -2826,6 +2826,21 @@ input[type="number"]::-webkit-outer-spin-button {
font-weight: 600;
}
/* Empty-state hint inside the sidebar streamer list (no streamers
added yet). Subtler than the full-page .empty-state fits the
narrow sidebar context. */
.streamer-list-empty {
padding: 12px 14px;
margin: 4px 8px;
color: var(--text-secondary);
font-size: 12px;
line-height: 1.45;
border: 1px dashed var(--border-soft);
border-radius: 6px;
text-align: center;
background: rgba(255, 255, 255, 0.02);
}
/* ============================================
VOD DURATION BADGE Twitch-style pill on the thumbnail
============================================ */