9ed8e261d4
Shimmer placeholders that mirror the layout of each library page so the real content slides in without shifting.
49 lines
1.7 KiB
Svelte
49 lines
1.7 KiB
Svelte
<script lang="ts">
|
|
type Variant = 'list' | 'grid' | 'album';
|
|
let { variant, count = 12 }: { variant: Variant; count?: number } = $props();
|
|
|
|
// Common shimmer class applied to every placeholder block.
|
|
const shimmer = 'animate-pulse bg-surface';
|
|
</script>
|
|
|
|
{#if variant === 'list'}
|
|
<div data-testid="skeleton-list" class="divide-y divide-border">
|
|
{#each Array.from({ length: count }) as _, i (i)}
|
|
<div data-skeleton-row class="flex items-center gap-3 px-3 py-3">
|
|
<span class="h-10 w-10 rounded-full {shimmer}"></span>
|
|
<span class="h-4 flex-1 rounded {shimmer}"></span>
|
|
<span class="h-3 w-20 rounded {shimmer}"></span>
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
{:else if variant === 'grid'}
|
|
<div
|
|
data-testid="skeleton-grid"
|
|
class="grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5"
|
|
>
|
|
{#each Array.from({ length: count }) as _, i (i)}
|
|
<div data-skeleton-card>
|
|
<div class="aspect-square w-full rounded {shimmer}"></div>
|
|
<div class="mt-2 h-4 w-3/4 rounded {shimmer}"></div>
|
|
<div class="mt-1 h-3 w-1/3 rounded {shimmer}"></div>
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
{:else}
|
|
<div data-testid="skeleton-album" class="space-y-6">
|
|
<div class="flex flex-col gap-4 md:flex-row md:items-end">
|
|
<div data-testid="skeleton-album-cover" class="h-60 w-60 rounded {shimmer}"></div>
|
|
<div class="flex-1 space-y-3">
|
|
<div class="h-8 w-3/4 rounded {shimmer}"></div>
|
|
<div class="h-4 w-1/3 rounded {shimmer}"></div>
|
|
<div class="h-4 w-1/4 rounded {shimmer}"></div>
|
|
</div>
|
|
</div>
|
|
<div class="space-y-2">
|
|
{#each Array.from({ length: 10 }) as _, i (i)}
|
|
<div class="h-6 w-full rounded {shimmer}"></div>
|
|
{/each}
|
|
</div>
|
|
</div>
|
|
{/if}
|