Add loading spinner to YouTube player windows

Song select: spinner shown via yt-loading class, removed when PLAYING.
Game page: spinner shown via :empty pseudo-class while iframe loads.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
main
Claude 2026-04-14 23:35:53 +00:00
parent 808da507f6
commit 9bc7a57d69
3 changed files with 45 additions and 1 deletions

View File

@ -77,6 +77,27 @@
border: 0;
}
.song-select-screen__yt-preview.yt-loading {
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.8);
}
.song-select-screen__yt-preview.yt-loading::after {
content: '';
width: 28px;
height: 28px;
border: 3px solid rgba(217, 70, 239, 0.2);
border-top-color: #d946ef;
border-radius: 50%;
animation: yt-spin 0.8s linear infinite;
}
@keyframes yt-spin {
to { transform: rotate(360deg); }
}
.song-select-screen__content {
position: relative;
z-index: 2;

View File

@ -72,8 +72,9 @@ function startYouTubePreview(song: Song, host: HTMLElement): () => void {
let player: YT.Player | null = null
let fadeIv = 0
// Clear any previous player content
// Clear any previous player content and show spinner
host.innerHTML = ''
host.classList.add('yt-loading')
const timer = window.setTimeout(() => {
loadYouTubeApi().then(() => {
@ -109,6 +110,7 @@ function startYouTubePreview(song: Song, host: HTMLElement): () => void {
onStateChange(e: YT.OnStateChangeEvent) {
if (destroyed || !player) return
if (e.data === YT.PlayerState.PLAYING) {
host.classList.remove('yt-loading')
const maxVol = MAX_VOLUME * 100
const step = (maxVol * FADE_STEP_MS) / FADE_IN_MS
fadeIv = window.setInterval(() => {

View File

@ -26,6 +26,27 @@
border: 0;
}
.ytPlayer:empty {
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.8);
}
.ytPlayer:empty::after {
content: '';
width: 28px;
height: 28px;
border: 3px solid rgba(217, 70, 239, 0.2);
border-top-color: #d946ef;
border-radius: 50%;
animation: yt-spin 0.8s linear infinite;
}
@keyframes yt-spin {
to { transform: rotate(360deg); }
}
.loadingOverlay {
position: fixed;
inset: 0;