Skeleton
Shimmering placeholder blocks and text lines that stand in for loading content.
'use client';
import { Avatar, Button, Card, Skeleton } from '@akhatmirzo/ui';
import { useState } from 'react';
export default function SkeletonLoadingCard() {
const [loading, setLoading] = useState(true);
return (
<div className="flex w-full max-w-md flex-col items-start gap-3">
<Button size="sm" onClick={() => setLoading((l) => !l)}>
{loading ? "Kontentni ko'rsatish" : 'Yuklanish holati'}
</Button>
<Card variant="outline" className="w-full" aria-busy={loading}>
<div className="flex items-center gap-3">
{loading ? (
<Skeleton variant="circle" className="size-10" />
) : (
<Avatar name="Malika Rahimova" />
)}
<div className="flex flex-1 flex-col gap-2">
{loading ? (
<Skeleton className="h-4 w-2/5" />
) : (
<b className="text-sm">Malika Rahimova</b>
)}
{loading ? (
<Skeleton className="h-3 w-1/4" />
) : (
<span className="text-xs text-text-muted">2 soat oldin</span>
)}
</div>
</div>
{loading ? (
<Skeleton.Text lines={3} />
) : (
<p className="text-sm">
Buyurtma vaqtida yetib keldi, kuryer juda xushmuomala edi. Keyingi safar ham shu
do'kondan olaman.
</p>
)}
</Card>
</div>
);
}
Import
import { Skeleton } from '@akhatmirzo/ui';When to use
- When you know the shape of the content — cards, lists, a profile, a table. The page doesn't jump once data arrives.
- Mirror the real content: a circle for the avatar, a short line for the title,
Skeleton.Textfor paragraphs. - For unknown shapes or short waits (after a button click), use a
Spinneror theloadingprop onButton. - Put
aria-busyon the parent — the skeletons themselves are hidden from screen readers.
Shapes
Set the size with className (h-4 w-32, size-10). variant="circle" gives a circle for
avatars; the default rect is a rectangle with rounded corners.
'use client';
import { Skeleton } from '@akhatmirzo/ui';
export default function SkeletonShapes() {
return (
<div className="flex flex-wrap items-center gap-4">
<Skeleton variant="circle" className="size-12" />
<Skeleton className="h-4 w-32" />
<Skeleton className="h-10 w-28 rounded-lg" />
</div>
);
}
Text lines
Skeleton.Text renders lines rows, with the last one at 60% width so it looks like a real
paragraph.
'use client';
import { Skeleton } from '@akhatmirzo/ui';
export default function SkeletonTextDemo() {
return (
<div className="grid w-full max-w-lg grid-cols-1 gap-6 sm:grid-cols-2">
<Skeleton.Text lines={1} />
<Skeleton.Text lines={4} />
</div>
);
}
Props
Skeleton
Skeleton accepts every other <div> attribute.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'rect' | 'circle' | 'rect' | circle is for avatar placeholders |
className | string | — | Size and shape: h-4 w-32, size-10, rounded-lg |
Skeleton.Text
Also exported as SkeletonText. Accepts the remaining <div> attributes.
| Prop | Type | Default | Description |
|---|---|---|---|
lines | number | 3 | Number of lines; with more than one, the last is 60% wide |
Accessibility
aria-hidden="true"— skeletons are invisible to screen readers, so empty blocks aren't announced.- Signal loading on the parent:
aria-busy={loading}(on theCardin the example above). Add a visually hidden "Loading" text if you need one. - Reduced motion. With "reduce motion" turned on, the shimmer becomes a gentle pulse.