Discover: meaningful filter colors + drop the asymmetric edge-fade

Colors now carry meaning instead of cycling by position:
- segments (Movies/TV, sort) → the app accent (they're modes, not categories)
- genre chips → a thematic colour per genre (Horror red, Comedy gold, Sci-Fi
  cyan, Romance pink, …) via a name→colour map; unmapped fall back to neutral
- provider chips → each service's brand colour (Netflix red, Disney+ blue, Max
  purple, Hulu green, …)
- era chips → a single warm amber; 'All/Any …' reset chips → neutral grey

Edge-fade: removed the mask-image from .vdsc-rail and .vdsc-chips. On short
filter rows only the left fade landed (dimming the first chip) while the right
fell on empty space — reading as a one-sided fade over everything.
This commit is contained in:
BoulderBadgeDad 2026-06-16 15:26:12 -07:00
parent b316d283f7
commit 80d504f94d
3 changed files with 39 additions and 29 deletions

View file

@ -891,19 +891,19 @@
<button class="vdsc-chip vdsc-chip--on" type="button" data-val="">All genres</button>
</div>
<div class="vdsc-chips" data-vdsc-chipset="providers" aria-label="Streaming service">
<button class="vdsc-chip vdsc-chip--on" type="button" data-val="">Any service</button>
<button class="vdsc-chip" type="button" data-val="8">Netflix</button>
<button class="vdsc-chip" type="button" data-val="9">Prime Video</button>
<button class="vdsc-chip" type="button" data-val="337">Disney+</button>
<button class="vdsc-chip" type="button" data-val="1899">Max</button>
<button class="vdsc-chip" type="button" data-val="350">Apple TV+</button>
<button class="vdsc-chip" type="button" data-val="15">Hulu</button>
<button class="vdsc-chip" type="button" data-val="531">Paramount+</button>
<button class="vdsc-chip" type="button" data-val="386">Peacock</button>
<button class="vdsc-chip vdsc-chip--reset vdsc-chip--on" type="button" data-val="">Any service</button>
<button class="vdsc-chip" type="button" data-val="8" style="--c: 229, 9, 20;">Netflix</button>
<button class="vdsc-chip" type="button" data-val="9" style="--c: 0, 168, 225;">Prime Video</button>
<button class="vdsc-chip" type="button" data-val="337" style="--c: 37, 99, 235;">Disney+</button>
<button class="vdsc-chip" type="button" data-val="1899" style="--c: 139, 92, 246;">Max</button>
<button class="vdsc-chip" type="button" data-val="350" style="--c: 200, 200, 210;">Apple TV+</button>
<button class="vdsc-chip" type="button" data-val="15" style="--c: 28, 231, 131;">Hulu</button>
<button class="vdsc-chip" type="button" data-val="531" style="--c: 14, 116, 240;">Paramount+</button>
<button class="vdsc-chip" type="button" data-val="386" style="--c: 147, 112, 219;">Peacock</button>
</div>
<div class="vdsc-browse-bottom">
<div class="vdsc-chips vdsc-chips--era" data-vdsc-chipset="decade" aria-label="Decade">
<button class="vdsc-chip vdsc-chip--on" type="button" data-val="">Any era</button>
<button class="vdsc-chip vdsc-chip--reset vdsc-chip--on" type="button" data-val="">Any era</button>
<button class="vdsc-chip" type="button" data-val="2020">2020s</button>
<button class="vdsc-chip" type="button" data-val="2010">2010s</button>
<button class="vdsc-chip" type="button" data-val="2000">2000s</button>

View file

@ -48,6 +48,18 @@
];
var GENRE_RAILS = ['Action', 'Adventure', 'Comedy', 'Drama', 'Science Fiction',
'Thriller', 'Horror', 'Animation', 'Fantasy', 'Romance', 'Documentary', 'Crime'];
// A thematic colour per genre so the chips read intentional, not random.
var GENRE_COLORS = {
'action': '239, 68, 68', 'adventure': '34, 197, 94', 'animation': '168, 85, 247',
'comedy': '245, 197, 24', 'crime': '120, 113, 108', 'documentary': '20, 184, 166',
'drama': '96, 165, 250', 'family': '74, 222, 128', 'fantasy': '192, 132, 252',
'history': '202, 138, 4', 'horror': '220, 38, 38', 'music': '236, 72, 153',
'mystery': '99, 102, 241', 'romance': '244, 114, 182', 'science fiction': '34, 211, 238',
'sci-fi & fantasy': '34, 211, 238', 'tv movie': '148, 163, 184', 'thriller': '100, 116, 139',
'war': '161, 98, 7', 'war & politics': '161, 98, 7', 'western': '180, 130, 80',
'kids': '74, 222, 128', 'reality': '251, 146, 60', 'soap': '244, 114, 182',
'talk': '148, 163, 184', 'news': '148, 163, 184',
};
var DECADE_RAILS = [
{ title: 'Best of the 2010s', q: 'kind=movie&decade=2010&sort=vote_average.desc' },
{ title: '2000s Favorites', q: 'kind=movie&decade=2000&sort=vote_average.desc' },
@ -366,9 +378,11 @@
}
function renderGenreChips() {
var box = $('[data-vdsc-chipset="genre"]'); if (!box) return;
box.innerHTML = '<button class="vdsc-chip vdsc-chip--on" type="button" data-val="">All genres</button>' +
box.innerHTML = '<button class="vdsc-chip vdsc-chip--reset vdsc-chip--on" type="button" data-val="">All genres</button>' +
(state.genres[state.sel.kind] || []).map(function (g) {
return '<button class="vdsc-chip" type="button" data-val="' + g.id + '">' + esc(g.name) + '</button>';
var c = GENRE_COLORS[(g.name || '').toLowerCase()];
return '<button class="vdsc-chip" type="button" data-val="' + g.id + '"' +
(c ? ' style="--c: ' + c + '"' : '') + '>' + esc(g.name) + '</button>';
}).join('');
state.sel.genre = '';
}

View file

@ -2273,9 +2273,7 @@ body[data-side="video"] #soulsync-toggle { display: none; }
.vdsc-toggle input { accent-color: rgb(var(--accent-rgb, 88 101 242)); width: 16px; height: 16px; cursor: pointer; }
.vdsc-hide-owned .vsr-card--owned { display: none; }
/* rails: soft edge fade + a gentle fade-in when filled + per-title hue on hover */
.vdsc-rail { -webkit-mask-image: linear-gradient(90deg, transparent, #000 18px, #000 calc(100% - 18px), transparent);
mask-image: linear-gradient(90deg, transparent, #000 18px, #000 calc(100% - 18px), transparent); }
/* rails: a gentle fade-in when filled + per-title hue on hover */
.vdsc-shelf--in .vdsc-rail { animation: vdscFade 0.45s ease both; }
@keyframes vdscFade { from { opacity: 0.35; } to { opacity: 1; } }
.vdsc-rail .vsr-card, .vdsc-grid .vsr-card { transition: transform 0.2s ease, box-shadow 0.2s ease; }
@ -2298,11 +2296,9 @@ body[data-side="video"] #soulsync-toggle { display: none; }
.vdsc-seg { display: inline-flex; gap: 6px; }
.vdsc-seg::before { display: none; }
/* chip rows (genres, providers, eras) — horizontally scrollable, edge-faded */
/* chip rows (genres, providers, eras) — horizontally scrollable */
.vdsc-chips { display: flex; gap: 8px; overflow-x: auto; padding: 4px 1px 7px; margin-top: 13px;
scrollbar-width: thin;
-webkit-mask-image: linear-gradient(90deg, transparent, #000 14px, #000 calc(100% - 14px), transparent);
mask-image: linear-gradient(90deg, transparent, #000 14px, #000 calc(100% - 14px), transparent); }
scrollbar-width: thin; }
.vdsc-chips::-webkit-scrollbar { height: 6px; }
.vdsc-chips::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.13); border-radius: 3px; }
.vdsc-chips--era { margin-top: 0; }
@ -2322,16 +2318,16 @@ body[data-side="video"] #soulsync-toggle { display: none; }
box-shadow: 0 9px 22px -9px rgba(var(--c, 120, 130, 240), 0.9),
0 0 0 1px rgba(var(--c, 120, 130, 240), 0.42), inset 0 1px 0 rgba(255, 255, 255, 0.25); }
/* the palette cycles across each row so a filter row reads colorful
(comma-separated triples so they slot into rgba(var(--c), a)) */
.vdsc-chip:nth-child(8n+1), .vdsc-seg-btn:nth-child(8n+1) { --c: 29, 185, 84; } /* green */
.vdsc-chip:nth-child(8n+2), .vdsc-seg-btn:nth-child(8n+2) { --c: 147, 112, 219; } /* purple */
.vdsc-chip:nth-child(8n+3), .vdsc-seg-btn:nth-child(8n+3) { --c: 100, 149, 237; } /* blue */
.vdsc-chip:nth-child(8n+4), .vdsc-seg-btn:nth-child(8n+4) { --c: 245, 158, 11; } /* amber */
.vdsc-chip:nth-child(8n+5), .vdsc-seg-btn:nth-child(8n+5) { --c: 236, 72, 153; } /* pink */
.vdsc-chip:nth-child(8n+6), .vdsc-seg-btn:nth-child(8n+6) { --c: 34, 211, 238; } /* cyan */
.vdsc-chip:nth-child(8n+7), .vdsc-seg-btn:nth-child(8n+7) { --c: 248, 113, 113; } /* coral */
.vdsc-chip:nth-child(8n), .vdsc-seg-btn:nth-child(8n) { --c: 168, 85, 247; } /* violet */
/* Colours carry meaning, not position:
- segments (Movies/TV, sort) the app accent (they're modes, not categories)
- genre chips a thematic colour per genre (set inline by JS)
- provider chips the service's brand colour (set inline in markup)
- era chips a single warm amber; reset chips ('All/Any …') neutral
so each --c is provided where it's meaningful and falls back to neutral here. */
.vdsc-seg-btn { --c: var(--accent-rgb, 29, 185, 84); }
.vdsc-chip--reset { --c: 148, 163, 184; } /* All genres / Any service / Any era */
.vdsc-chips--era .vdsc-chip { --c: 245, 158, 11; }
.vdsc-chips--era .vdsc-chip--reset { --c: 148, 163, 184; }
.vdsc-browse-bottom { display: flex; align-items: center; gap: 16px; margin-top: 12px; }
.vdsc-browse-bottom .vdsc-chips { flex: 1; min-width: 0; margin-top: 0; }