ui: color-coded chip groups in streams header with per-chip shade variation

Device chips: blue, resolution chips: teal, codec chips: amber.
Alternating bg shades within each group to visually separate chips.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gmer4Lfe
2026-05-31 21:59:16 -04:00
co-authored by Claude Sonnet 4.6
parent 89df1a98db
commit 0319b13304
2 changed files with 32 additions and 7 deletions
+14 -4
View File
@@ -753,11 +753,21 @@ mark { background: #5d4037; color: #ffcc80; border-radius: 2px; }
.vv-server-badge { background: #333; border: 1px solid #555; color: #aaa;
font-size: 10px; padding: 1px 7px; border-radius: 10px; }
.vv-server-badge-sm { font-size: 9px; padding: 1px 6px; flex-shrink: 0; }
/* Device type chips — shown right of server badges when sessions are active */
/* Chip groups — server badge row */
.vv-device-sep { color: #2a2a2a; font-size: 12px; margin: 0 2px; user-select: none; }
.vv-device-chip { font-size: 10px; color: #666; padding: 1px 7px;
border-radius: 10px; background: #181818; border: 1px solid #252525;
white-space: nowrap; }
/* shared chip geometry */
.vv-device-chip,
.vv-chip-device, .vv-chip-res, .vv-chip-codec {
font-size: 10px; padding: 1px 7px; border-radius: 10px;
white-space: nowrap; border: 1px solid; }
/* device — blue */
.vv-chip-device { color: #5a9ec8; background: #0d1e2e; border-color: #1c3f5c; }
/* resolution — teal */
.vv-chip-res { color: #4aaa9a; background: #0b1e1c; border-color: #1a4540; }
/* codec — amber */
.vv-chip-codec { color: #b38820; background: #201500; border-color: #483300; }
/* legacy fallback */
.vv-device-chip { color: #666; background: #181818; border-color: #252525; }
.vv-stream-empty { color: #555; font-style: italic; font-size: 12px; margin: 4px 0; }
.vv-stream-empty span { font-size: 11px; color: #444; }
.vv-stream-row { margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid #282828; }
+18 -3
View File
@@ -1447,6 +1447,21 @@ function vvRenderStreams() {
: `<span class="vv-server-badge" style="color:#444;">${n}</span>`;
}).join('');
// Per-chip shade: alternate bg brightness within a group to visually separate chips
// shades[0] = base bg, shades[1] = slightly lighter, cycling per index
function vvChipShade(cls, i) {
const shades = {
'vv-chip-device': ['#0d1e2e', '#112436'],
'vv-chip-res': ['#0b1e1c', '#0e2422'],
'vv-chip-codec': ['#201500', '#261900'],
};
const bg = (shades[cls] ?? ['',''])[i % 2];
return bg ? ` style="background:${bg};"` : '';
}
function vvChip(cls, label, i) {
return `<span class="${cls}"${vvChipShade(cls, i)}>${label}</span>`;
}
// Device type summary — e.g. "3 Android 1 iOS 2 Roku"
const devCounts = {};
sessions.forEach(s => {
@@ -1455,7 +1470,7 @@ function vvRenderStreams() {
});
const deviceBar = Object.entries(devCounts)
.sort((a, b) => b[1] - a[1])
.map(([t, n]) => `<span class="vv-device-chip">${n} ${t}</span>`)
.map(([t, n], i) => vvChip('vv-chip-device', `${n} ${t}`, i))
.join('');
const deviceSection = deviceBar
? `<span class="vv-device-sep">·</span>${deviceBar}`
@@ -1476,7 +1491,7 @@ function vvRenderStreams() {
});
const resOrder = ['4K', '1080p', '720p', '480p'];
const resBar = resOrder.filter(r => resCounts[r])
.map(r => `<span class="vv-device-chip">${resCounts[r]} ${r}</span>`)
.map((r, i) => vvChip('vv-chip-res', `${resCounts[r]} ${r}`, i))
.join('');
const resSection = resBar ? `<span class="vv-device-sep">·</span>${resBar}` : '';
@@ -1493,7 +1508,7 @@ function vvRenderStreams() {
});
const codecBar = Object.entries(codecCounts)
.sort((a, b) => b[1] - a[1])
.map(([c, n]) => `<span class="vv-device-chip">${n} ${c}</span>`)
.map(([c, n], i) => vvChip('vv-chip-codec', `${n} ${c}`, i))
.join('');
const codecSection = codecBar ? `<span class="vv-device-sep">·</span>${codecBar}` : '';