feat(immersive): create unified ImmersivePlayer component
New component architecture: - ImmersivePlayer.svelte: Main container with tab system - ImmersiveHeader.svelte: Tabs (lyrics/credits/suggestions/visualizer) - ImmersiveControls.svelte: Bottom bar with all playback controls - ImmersiveArtwork.svelte: Album art with floating/vinyl variants - ImmersiveBackground.svelte: Optimized blur background (from Phase 1) Panel components: - LyricsPanel: Wrapper for existing LyricsLines - CreditsPanel: Placeholder (Phase 3) - SuggestionsPanel: Placeholder (Phase 4) - VisualizerPanel: Placeholder (Phase 5) Shared components: - ProgressBar: Reusable seek bar with keyboard support - VolumeSlider: Reusable volume control Features: - Tab-based navigation (L/C/S/V keyboard shortcuts) - Auto-hide UI after 4 seconds of inactivity - Full keyboard control (Space, Arrows, Escape) - Responsive layout (desktop/tablet/mobile) - Accessibility: ARIA roles, focus management
This commit is contained in:
1 parent
513614466e
commit
7c9f1820f8
11 files changed
+1730
No files matched your search
@@ -0,0 +1,58 @@
|
||||
<script lang="ts">
|
||||
import { t } from '$lib/i18n';
|
||||
|
||||
interface Props {
|
||||
trackId?: number;
|
||||
artistId?: number;
|
||||
}
|
||||
|
||||
let { trackId, artistId }: Props = $props();
|
||||
|
||||
// TODO: Implement suggestions fetching in Phase 4
|
||||
let isLoading = $state(false);
|
||||
</script>
|
||||
|
||||
<div class="suggestions-panel">
|
||||
<div class="placeholder">
|
||||
<span class="placeholder-icon">📻</span>
|
||||
<span class="placeholder-text">{$t('player.suggestionsComingSoon') || 'Suggestions coming soon'}</span>
|
||||
<span class="placeholder-hint">Artist Radio, Track Radio, Similar Tracks...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.suggestions-panel {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
height: 100%;
|
||||
min-height: 200px;
|
||||
color: var(--alpha-40, rgba(255, 255, 255, 0.4));
|
||||
}
|
||||
|
||||
.placeholder-icon {
|
||||
font-size: 32px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.placeholder-text {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.placeholder-hint {
|
||||
font-size: 13px;
|
||||
color: var(--alpha-30, rgba(255, 255, 255, 0.3));
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user