Components
- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input OTP
- Input Group
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
- New Component
Elements
Charts
Icons
import { Skeleton } from "@/components/ui/skeleton";
export const SkeletonDemo = () => (
<div className="flex flex-col gap-8">
{/* Card skeleton */}
<div className="flex flex-col gap-3">
<Skeleton className="h-40 w-full rounded-xl" />
<div className="flex items-center gap-3">
<Skeleton className="size-10 shrink-0 rounded-full" />
<div className="flex flex-1 flex-col gap-2">
<Skeleton className="h-4 w-3/4" />
<Skeleton className="h-3 w-1/2" />
</div>
</div>
</div>
{/* List skeleton */}
<div className="flex flex-col gap-3">
{Array.from({ length: 3 }).map((_, i) => (
<div key={i} className="flex items-center gap-3">
<Skeleton className="size-9 shrink-0 rounded-md" />
<div className="flex flex-1 flex-col gap-1.5">
<Skeleton className="h-3.5 w-2/5" />
<Skeleton className="h-3 w-3/5" />
</div>
<Skeleton className="h-6 w-14 rounded-full" />
</div>
))}
</div>
{/* Text block skeleton */}
<div className="flex flex-col gap-2">
<Skeleton className="h-4 w-full" />
<Skeleton className="h-4 w-full" />
<Skeleton className="h-4 w-4/5" />
<Skeleton className="h-4 w-3/5" />
</div>
</div>
);Usage
Match the skeleton shape to the content it replaces. Use rounded-full for avatars, rounded-xl for cards, and default rounded-md for text lines and thumbnails.
{/* Avatar + text row */}
<div className="flex items-center gap-3">
<Skeleton className="size-10 rounded-full" />
<div className="flex flex-1 flex-col gap-2">
<Skeleton className="h-4 w-3/4" />
<Skeleton className="h-3 w-1/2" />
</div>
</div>In a list
{isLoading
? Array.from({ length: 5 }).map((_, i) => (
<div key={i} className="flex items-center gap-3">
<Skeleton className="size-9 rounded-md" />
<div className="flex flex-1 flex-col gap-1.5">
<Skeleton className="h-3.5 w-2/5" />
<Skeleton className="h-3 w-3/5" />
</div>
</div>
))
: items.map((item) => <ListItem key={item.id} {...item} />)}Props
Skeleton is a plain <div> — pass any className to control size and shape.
| Prop | Type | Description |
|---|---|---|
className | string | Width, height, border-radius overrides |
Specs
# Mint — Skeleton Specs
## Component
- name: skeleton
- file: registry/mint/skeleton.tsx
- installs to: components/ui/skeleton.tsx
- dependencies: none
- registryDependencies: none
## What is it
An animated placeholder that mimics the shape and layout of real content while
data is loading. It renders as a single styled `<div>` — size and shape are
always controlled by the caller via `className`. Prefer Skeleton over spinners
when the content structure is known in advance; do not use it for actions or
interactive states.
## Visual identity
Renders as a soft mint-green tinted block (0.375rem radius via `rounded-md`)
with an `animate-pulse` fade cycle. Uses the `--accent` surface colour, giving
a light, low-contrast shimmer that stays true to Mint without drawing
attention away from real content.
## Design tokens
--accent: oklch(0.92 0.05 155) / oklch(0.26 0.05 155) — pulse surface (light / dark)
## States
- animate-pulse: continuous opacity fade; always active while the skeleton is mounted
## Conventions
- Set width and height on the caller: e.g. `className="h-4 w-3/4"`
- Use `rounded-full` for circular avatars, `rounded-xl` for card shapes, default `rounded-md` for text lines and thumbnails
- Repeat in a list with `Array.from({ length: n })` — use index as key only while loading
- Replace the entire skeleton tree with real content in a single render; avoid partial swaps
- Sub-components expose `data-slot="skeleton"` for CSS targetingInstallation
$ npx shadcn add \https://gin-design.vercel.app/skeleton