🚀 Auto-adapting shimmer loader untuk Svelte 5 yang otomatis menyesuaikan bentuk, ukuran, dan posisi dengan UI asli Anda. Tidak ada lagi skeleton manual yang tidak presisi!
cacheKey, shimmer presis di load berikutnyaskeleton untuk first-load yang akurat# npm
npm install @ubay182/svelte-auto-shimmer
# yarn
yarn add @ubay182/svelte-auto-shimmer
# pnpm
pnpm add @ubay182/svelte-auto-shimmer
<script lang="ts">
import { Shimmer } from "@ubay182/svelte-auto-shimmer";
let loading = $state(true);
let data: { title: string; description: string } | null = $state(null);
</script>
<Shimmer {loading} cacheKey="my-card">
<!-- Konten Asli -->
{#snippet children()}
<div class="card">
<h2>{data?.title}</h2>
<p>{data?.description}</p>
</div>
{/snippet}
<!-- Blueprint Skeleton (untuk first load) -->
{#snippet skeleton()}
<div class="card">
<h2>Loading title...</h2>
<p>Loading description...</p>
</div>
{/snippet}
</Shimmer>
<script lang="ts">
import { onMount } from "svelte";
import { Shimmer } from "@ubay182/svelte-auto-shimmer";
let loading = $state(true);
let user: {
name: string;
bio: string;
avatar: string;
tags: string[];
} | null = $state(null);
const fetchData = () => {
loading = true;
const names = ["Ubaidillah Rahman", "Budi Santoso", "Siti Aminah"];
const randomName = names[Math.floor(Math.random() * names.length)];
setTimeout(() => {
user = {
name: randomName,
bio: "Fullstack Developer & Svelte Enthusiast.",
avatar: "https://placehold.co/100x100/e2e8f0/475569?text=UR",
tags: ["Svelte", "TypeScript", "UI/UX", "Frontend", "Backend", "DevOps"],
};
loading = false;
}, 5000);
};
onMount(() => fetchData());
</script>
<Shimmer
{loading}
cacheKey="user-profile"
border="1px solid #e5e7eb"
borderRadius="12px"
boxShadow="0 4px 12px rgba(0,0,0,0.05)"
bgColor="#ffffff"
padding="1.5rem"
>
<!-- KONTEN ASLI -->
{#snippet children()}
<div class="profile-content">
{#if user?.avatar}
<img src={user.avatar} alt={user.name} class="avatar" />
{/if}
<h2 class="title">{user?.name || "Loading Name..."}</h2>
<p class="bio">{user?.bio || "Loading bio..."}</p>
<!-- Tags Container dengan Flex Wrap -->
{#if user?.tags}
<div class="tags">
{#each user.tags as tag (tag)}
<span class="tag">{tag}</span>
{/each}
</div>
{/if}
<a href="/profile" class="btn action">View Profile</a>
</div>
{/snippet}
<!-- SKELETON BLUEPRINT -->
{#snippet skeleton()}
<div class="profile-content">
<div class="avatar-placeholder"></div>
<h2 class="title-placeholder"></h2>
<p class="bio-placeholder"></p>
<div class="tags">
<span class="tag-placeholder"></span>
<span class="tag-placeholder"></span>
<span class="tag-placeholder"></span>
<span class="tag-placeholder"></span>
<span class="tag-placeholder"></span>
<span class="tag-placeholder"></span>
</div>
<button class="btn action">View Profile</button>
</div>
{/snippet}
</Shimmer>
| Prop | Tipe | Default | Deskripsi |
|---|---|---|---|
| loading | boolean | false | Kontrol state loading (true = tampilkan shimmer) |
| cacheKey | string | - | Unique key untuk caching dimensi. Wajib agar shimmer presis di refresh berikutnya |
| border | string | '1px solid #e5e7eb' | CSS border untuk wrapper container |
| borderRadius | string | '8px' | CSS border-radius untuk wrapper |
| boxShadow | string | '0 2px 8px rgba(0,0,0,0.05)' | CSS box-shadow untuk wrapper |
| bgColor | string | '#ffffff' | Background color wrapper |
| padding | string | '1.5rem' | Padding internal wrapper (shimmer blocks diukur relatif terhadap area ini) |
| Snippet | Deskripsi |
|---|---|
| children | Konten asli yang akan ditampilkan saat loading=false |
| skeleton | Blueprint HTML untuk first-load shimmer. Strukturnya sebaiknya mirip dengan konten asli agar pengukuran akurat |
<script lang="ts">
import { onMount } from "svelte";
import { Shimmer } from "@ubay182/svelte-auto-shimmer";
let loading = $state(true);
let user: any = $state(null);
const fetchUser = async (id: number) => {
loading = true;
try {
const res = await fetch(`https://api.example.com/users/${id}`);
user = await res.json();
} finally {
loading = false;
}
};
onMount(() => fetchUser(123));
</script>
<Shimmer {loading} cacheKey="user-profile">
{#snippet children()}
<div class="profile">
<img src={user?.avatar} alt={user?.name} class="avatar" />
<h1>{user?.name}</h1>
<p>{user?.bio}</p>
</div>
{/snippet}
{#snippet skeleton()}
<div class="profile">
<div class="avatar-placeholder"></div>
<h1 class="name-placeholder"></h1>
<p class="bio-placeholder"></p>
</div>
{/snippet}
</Shimmer>
Gunakan data-shimmer-ignore untuk mengecualikan elemen tertentu dari shimmer:
<div>
<h2>Title</h2>
<p data-shimmer-ignore>Ini tidak akan jadi shimmer</p>
<button>Action</button>
</div>
<div data-shimmer-skip>
<!-- Konten ini tidak akan di-scan untuk shimmer -->
<StaticBanner />
</div>
# Clone repo
git clone https://github.com/ubay1/svelte-auto-shimmer.git
cd svelte-auto-shimmer
# Install dependencies
npm install
# Run dev server
npm run dev
# Build library
npm run build
# Preview build output
npm run preview
Contributions welcome!
Silakan:
git checkout -b feat/amazing-feature)git commit -m 'Add amazing feature')git push origin feat/amazing-feature)Pastikan:
MIT License - see LICENSE file for details.