this repo has no description
1<script lang="ts">
2 type Variant = 'line' | 'circle' | 'card'
3 type Size = 'tiny' | 'short' | 'medium' | 'full'
4
5 interface Props {
6 variant?: Variant
7 size?: Size
8 lines?: number
9 class?: string
10 }
11
12 let { variant = 'line', size = 'full', lines = 1, class: className = '' }: Props = $props()
13</script>
14
15{#if variant === 'card'}
16 <div class="skeleton-card {className}">
17 <div class="skeleton-header">
18 <div class="skeleton-line short"></div>
19 <div class="skeleton-line tiny"></div>
20 </div>
21 {#each Array(lines) as _}
22 <div class="skeleton-line"></div>
23 {/each}
24 <div class="skeleton-line medium"></div>
25 </div>
26{:else if variant === 'circle'}
27 <div class="skeleton-circle {className}"></div>
28{:else}
29 {#each Array(lines) as _, i}
30 <div class="skeleton-line {size} {className}" class:last={i === lines - 1}></div>
31 {/each}
32{/if}
33
34<style>
35 .skeleton-card {
36 background: var(--bg-card);
37 border: 1px solid var(--border-color);
38 border-radius: var(--radius-md);
39 padding: var(--space-3);
40 }
41
42 .skeleton-header {
43 display: flex;
44 gap: var(--space-2);
45 margin-bottom: var(--space-2);
46 }
47
48 .skeleton-line {
49 height: 14px;
50 background: var(--bg-tertiary);
51 border-radius: var(--radius-sm);
52 animation: skeleton-pulse 1.5s ease-in-out infinite;
53 margin-bottom: var(--space-1);
54 }
55
56 .skeleton-line.last {
57 margin-bottom: 0;
58 }
59
60 .skeleton-line.tiny { width: 50px; }
61 .skeleton-line.short { width: 80px; }
62 .skeleton-line.medium { width: 60%; }
63 .skeleton-line.full { width: 100%; }
64
65 .skeleton-circle {
66 width: 40px;
67 height: 40px;
68 border-radius: 50%;
69 background: var(--bg-tertiary);
70 animation: skeleton-pulse 1.5s ease-in-out infinite;
71 }
72
73 @keyframes skeleton-pulse {
74 0%, 100% { opacity: 1; }
75 50% { opacity: 0.4; }
76 }
77</style>