finally got the playlist score bar gradient to clip at the score
This commit is contained in:
parent
fbba09f5b6
commit
17890e42e5
@ -15,5 +15,5 @@
|
||||
|
||||
## Shell command guidance
|
||||
|
||||
- Whitelisted commands: `grep`
|
||||
- DO NOT USE: `cd` (prefer `pwd`)
|
||||
- Dont' use `cd`, prefer `pwd`
|
||||
- Dont' use `rg`, prefer `grep -r`
|
||||
|
||||
@ -62,11 +62,15 @@ let playlistState: Record<number, PlaylistState> = {};
|
||||
|
||||
function togglePlaylist(id: number) {
|
||||
const currentlyExpanded = Boolean(expanded[id]);
|
||||
expanded = { ...expanded, [id]: !currentlyExpanded };
|
||||
const nextExpanded: Record<number, boolean> = {};
|
||||
if (!currentlyExpanded) {
|
||||
nextExpanded[id] = true;
|
||||
}
|
||||
expanded = nextExpanded;
|
||||
if (!currentlyExpanded) {
|
||||
const state = playlistState[id];
|
||||
const offset = state ? state.offset : 0;
|
||||
loadPlaylistMaps(id, offset);
|
||||
const currentOffset = state && typeof state.offset === 'number' ? state.offset : 0;
|
||||
loadPlaylistMaps(id, currentOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,16 +226,9 @@ function scorePercent(avgScore: number | undefined | null): number | null {
|
||||
<span class="map-count">{playlist.stats?.totalMaps ?? 0} maps</span>
|
||||
</div>
|
||||
{#if scorePercent(playlist.stats?.avgScore) !== null}
|
||||
<div
|
||||
class="row-score"
|
||||
data-gradient={scorePercent(playlist.stats?.avgScore)! > 50 ? 'true' : 'false'}
|
||||
>
|
||||
<div class="score-bar">
|
||||
<div
|
||||
class="score-bar-fill"
|
||||
style={`width: ${scorePercent(playlist.stats?.avgScore) ?? 0}%`}
|
||||
></div>
|
||||
</div>
|
||||
{@const pct = scorePercent(playlist.stats?.avgScore) ?? 0}
|
||||
<div class="row-score">
|
||||
<div class="score-bar" style={`--score-fill:${pct}%`}></div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="row-sub">
|
||||
@ -255,14 +252,15 @@ function scorePercent(avgScore: number | undefined | null): number | null {
|
||||
</button>
|
||||
|
||||
{#if expanded[playlist.playlistId]}
|
||||
{@const state = playlistState[playlist.playlistId]}
|
||||
<div class="row-body">
|
||||
{#if playlistState[playlist.playlistId]?.loading}
|
||||
{#if state?.loading}
|
||||
<div class="row-status">Loading songs…</div>
|
||||
{:else if playlistState[playlist.playlistId]?.error}
|
||||
<div class="row-status error">{playlistState[playlist.playlistId]?.error}</div>
|
||||
{:else if playlistState[playlist.playlistId]?.maps?.length}
|
||||
{:else if state?.error}
|
||||
<div class="row-status error">{state.error}</div>
|
||||
{:else if state?.maps?.length}
|
||||
<div class="songs-grid">
|
||||
{#each playlistState[playlist.playlistId].maps as card (card.id)}
|
||||
{#each state.maps as card (card.id)}
|
||||
<MapCard
|
||||
hash={card.hash}
|
||||
coverURL={card.coverURL}
|
||||
@ -278,35 +276,34 @@ function scorePercent(avgScore: number | undefined | null): number | null {
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
{#if playlistState[playlist.playlistId]?.total}
|
||||
{#if state.total && state.total > SONGS_PER_PAGE}
|
||||
<div class="row-pagination">
|
||||
<button
|
||||
class="pager-btn"
|
||||
on:click={() => loadPlaylistMaps(playlist.playlistId, Math.max(0, playlistState[playlist.playlistId].offset - SONGS_PER_PAGE))}
|
||||
disabled={playlistState[playlist.playlistId].offset === 0 || playlistState[playlist.playlistId].loading}
|
||||
on:click={() => loadPlaylistMaps(playlist.playlistId, Math.max(0, (state.offset ?? 0) - SONGS_PER_PAGE))}
|
||||
disabled={(state.offset ?? 0) === 0 || state.loading}
|
||||
>
|
||||
Prev {SONGS_PER_PAGE}
|
||||
</button>
|
||||
<span class="row-status">
|
||||
{#if playlistState[playlist.playlistId].total === 0}
|
||||
{#if state.total === 0}
|
||||
No songs
|
||||
{:else}
|
||||
Showing {playlistState[playlist.playlistId].offset + 1}
|
||||
Showing {(state.offset ?? 0) + 1}
|
||||
-
|
||||
{Math.min(
|
||||
playlistState[playlist.playlistId].offset + playlistState[playlist.playlistId].maps.length,
|
||||
playlistState[playlist.playlistId].total ?? 0
|
||||
(state.offset ?? 0) + state.maps.length,
|
||||
state.total ?? 0
|
||||
)}
|
||||
of {playlistState[playlist.playlistId].total}
|
||||
of {state.total}
|
||||
{/if}
|
||||
</span>
|
||||
<button
|
||||
class="pager-btn"
|
||||
on:click={() => loadPlaylistMaps(playlist.playlistId, playlistState[playlist.playlistId].offset + SONGS_PER_PAGE)}
|
||||
on:click={() => loadPlaylistMaps(playlist.playlistId, (state.offset ?? 0) + SONGS_PER_PAGE)}
|
||||
disabled={
|
||||
playlistState[playlist.playlistId].loading ||
|
||||
(playlistState[playlist.playlistId].offset + playlistState[playlist.playlistId].maps.length) >=
|
||||
(playlistState[playlist.playlistId].total ?? 0)
|
||||
state.loading ||
|
||||
((state.offset ?? 0) + state.maps.length) >= (state.total ?? 0)
|
||||
}
|
||||
>
|
||||
Next {SONGS_PER_PAGE}
|
||||
@ -431,25 +428,25 @@ function scorePercent(avgScore: number | undefined | null): number | null {
|
||||
width: 100%;
|
||||
height: 0.5rem;
|
||||
border-radius: 999px;
|
||||
background: rgba(34, 211, 238, 0.15);
|
||||
background-color: rgba(34, 211, 238, 0.15);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.score-bar-fill {
|
||||
.score-bar::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-radius: inherit;
|
||||
background: var(--score-gradient, var(--score-default));
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
.row-score[data-gradient='true'] .score-bar-fill {
|
||||
--score-gradient: linear-gradient(90deg, var(--color-neon-fuchsia), var(--color-neon));
|
||||
}
|
||||
|
||||
.row-score[data-gradient='false'] .score-bar-fill {
|
||||
--score-gradient: rgba(148, 163, 184, 0.35);
|
||||
background: linear-gradient(90deg, var(--color-neon-fuchsia), var(--color-neon));
|
||||
/* Reveal only the first N% of the full-width gradient */
|
||||
-webkit-mask-image: linear-gradient(90deg, #000 0 var(--score-fill, 0%), transparent var(--score-fill, 0%) 100%);
|
||||
mask-image: linear-gradient(90deg, #000 0 var(--score-fill, 0%), transparent var(--score-fill, 0%) 100%);
|
||||
/* Fallback for environments without mask-image support */
|
||||
clip-path: inset(0 calc(100% - var(--score-fill, 0%)) 0 0 round 999px);
|
||||
transition: -webkit-mask-image 0.3s ease, mask-image 0.3s ease, clip-path 0.3s ease;
|
||||
}
|
||||
|
||||
.row-arrow {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user