Komponen / Tampilan data
Skeleton
Placeholder berdenyut yang meniru tata letak isi selagi data dimuat, agar layar tidak melompat saat data tiba.
Bentuk
Text (160×12) untuk baris teks, Text large (240×20) untuk judul atau angka besar, Circle (32) untuk avatar, Rect (160×96) untuk gambar, grafik, atau kartu.
import { Skeleton } from '@divistant/circca-react';
export default function Example() {
return (
<div className="flex flex-wrap items-end gap-6">
<Skeleton shape="text" />
<Skeleton shape="text-large" />
<Skeleton shape="circle" />
<Skeleton shape="rect" />
</div>
);
}Memuat daftar
Susun beberapa Skeleton mengikuti baris aslinya; atur lebar dengan `width` agar tidak seragam.
import { Skeleton } from '@divistant/circca-react';
export default function Example() {
return (
<div aria-busy="true" aria-label="Memuat daftar opportunity" className="grid max-w-md">
{[0, 1, 2].map(i => (
<div key={i} className="flex items-center gap-3 border-b border-default py-3 last:border-b-0">
<Skeleton shape="circle" />
<div className="grid flex-1 gap-2">
<Skeleton width="70%" />
<Skeleton width="40%" />
</div>
<Skeleton width={64} />
</div>
))}
</div>
);
}Kartu yang dimuat ulang
Wadah memakai aria-busy selama memuat, lalu isi asli menggantikan Skeleton di tempat yang sama.
import { useEffect, useState } from 'react';
import { Button, ProgressBar, Skeleton } from '@divistant/circca-react';
export default function Example() {
const [loading, setLoading] = useState(true);
useEffect(() => {
if (!loading) return;
const t = setTimeout(() => setLoading(false), 1500);
return () => clearTimeout(t);
}, [loading]);
return (
<div className="grid max-w-xs gap-3">
<div aria-busy={loading} aria-live="polite" className="grid gap-3 rounded-xl border border-default bg-default p-4">
{loading ? (
<>
<Skeleton width={120} />
<Skeleton shape="text-large" width="80%" />
<Skeleton height={4} width="100%" className="rounded-full" />
</>
) : (
<>
<p className="type-caption-default text-muted">PO-2026-0142 · PT Pelanggan Contoh A</p>
<p className="type-heading-small text-default">Rp 60.000.000 terbayar</p>
<ProgressBar label="Termin terbayar" value={60} tone="success" />
</>
)}
</div>
<Button size="sm" onClick={() => setLoading(true)} disabled={loading} className="justify-self-start">
Muat ulang
</Button>
</div>
);
}