92 lines
2.6 KiB
Svelte
92 lines
2.6 KiB
Svelte
<script lang="ts">
|
|
interface Props {
|
|
type?: "card" | "text" | "circle" | "banner" | "row";
|
|
count?: number;
|
|
width?: string;
|
|
height?: string;
|
|
aspectRatio?: "square" | "video" | "portrait";
|
|
}
|
|
|
|
let {
|
|
type = "card",
|
|
count = 1,
|
|
width = "100%",
|
|
height = "auto",
|
|
aspectRatio = "square",
|
|
}: Props = $props();
|
|
|
|
const aspectClasses = {
|
|
square: "aspect-square",
|
|
video: "aspect-video",
|
|
portrait: "aspect-[2/3]",
|
|
};
|
|
</script>
|
|
|
|
{#if type === "card"}
|
|
<div class="flex gap-4 overflow-hidden">
|
|
{#each Array(count) as _, i (i)}
|
|
<div class="flex-shrink-0 w-36 animate-pulse">
|
|
<div class="w-full {aspectClasses[aspectRatio]} bg-[var(--color-surface)] rounded-lg shimmer"></div>
|
|
<div class="mt-2 space-y-2">
|
|
<div class="h-4 bg-[var(--color-surface)] rounded shimmer" style="width: 80%"></div>
|
|
<div class="h-3 bg-[var(--color-surface)] rounded shimmer" style="width: 60%"></div>
|
|
</div>
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
{:else if type === "banner"}
|
|
<div class="animate-pulse">
|
|
<div class="h-[500px] bg-[var(--color-surface)] rounded-xl shimmer"></div>
|
|
</div>
|
|
{:else if type === "circle"}
|
|
<div class="flex gap-4">
|
|
{#each Array(count) as _, i (i)}
|
|
<div class="flex flex-col items-center animate-pulse">
|
|
<div class="w-20 h-20 rounded-full bg-[var(--color-surface)] shimmer"></div>
|
|
<div class="mt-2 h-3 w-16 bg-[var(--color-surface)] rounded shimmer"></div>
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
{:else if type === "row"}
|
|
<div class="space-y-4">
|
|
{#each Array(count) as _, i (i)}
|
|
<div class="flex gap-4 animate-pulse">
|
|
<div class="w-16 h-16 rounded bg-[var(--color-surface)] shimmer flex-shrink-0"></div>
|
|
<div class="flex-1 space-y-2 py-2">
|
|
<div class="h-4 bg-[var(--color-surface)] rounded shimmer" style="width: 70%"></div>
|
|
<div class="h-3 bg-[var(--color-surface)] rounded shimmer" style="width: 50%"></div>
|
|
</div>
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
{:else if type === "text"}
|
|
<div class="space-y-2 animate-pulse">
|
|
{#each Array(count) as _, i (i)}
|
|
<div class="h-4 bg-[var(--color-surface)] rounded shimmer" style="width: {width}; height: {height}"></div>
|
|
{/each}
|
|
</div>
|
|
{/if}
|
|
|
|
<style>
|
|
@keyframes shimmer {
|
|
0% {
|
|
background-position: -1000px 0;
|
|
}
|
|
100% {
|
|
background-position: 1000px 0;
|
|
}
|
|
}
|
|
|
|
.shimmer {
|
|
animation: shimmer 2s infinite linear;
|
|
background: linear-gradient(
|
|
to right,
|
|
var(--color-surface) 0%,
|
|
rgba(255, 255, 255, 0.05) 20%,
|
|
var(--color-surface) 40%,
|
|
var(--color-surface) 100%
|
|
);
|
|
background-size: 1000px 100%;
|
|
}
|
|
</style>
|