Primitive / Atomstable

Skeleton

Loading placeholder surface with reduced-motion fallback.

@glinui/uiComponent: skeleton

Installation$

Install from the package for shared ownership or from the registry for copy-paste control.

Package Manager$

pnpm add @glinui/ui @glinui/tokens

Registry$

pnpm dlx @glinui/cli@latest add skeleton

Usage$

Skeleton renders a shimmer-animated placeholder shape while content loads. A gradient sweep replaces the traditional pulse for a polished loading state. Animation is disabled automatically under prefers-reduced-motion.

Basic$

TSX
1import { Skeleton } from "@glinui/ui"
2
3export function SkeletonBasicDemo() {
4return <Skeleton className="h-5 w-48" />
5}

Examples$

Variants$

Six visual variants to match any surface context.

Default
Glass
Liquid
Matte
Outline
Ghost
TSX
1import { Skeleton } from "@glinui/ui"
2
3export function SkeletonVariantDemo() {
4return (
5 <div className="space-y-4">
6 <div className="space-y-1">
7 <span className="text-xs font-medium text-neutral-500 dark:text-neutral-400">Default</span>
8 <Skeleton variant="default" className="h-5 w-64" />
9 </div>
10 <div className="space-y-1">
11 <span className="text-xs font-medium text-neutral-500 dark:text-neutral-400">Glass</span>
12 <Skeleton variant="glass" className="h-5 w-64" />
13 </div>
14 <div className="space-y-1">
15 <span className="text-xs font-medium text-neutral-500 dark:text-neutral-400">Liquid</span>
16 <Skeleton variant="liquid" className="h-5 w-64" />
17 </div>
18 <div className="space-y-1">
19 <span className="text-xs font-medium text-neutral-500 dark:text-neutral-400">Matte</span>
20 <Skeleton variant="matte" className="h-5 w-64" />
21 </div>
22 <div className="space-y-1">
23 <span className="text-xs font-medium text-neutral-500 dark:text-neutral-400">Outline</span>
24 <Skeleton variant="outline" className="h-5 w-64" />
25 </div>
26 <div className="space-y-1">
27 <span className="text-xs font-medium text-neutral-500 dark:text-neutral-400">Ghost</span>
28 <Skeleton variant="ghost" className="h-5 w-64" />
29 </div>
30 </div>
31)
32}

Sizes$

TSX
1import { Skeleton } from "@glinui/ui"
2
3export function SkeletonSizeDemo() {
4return (
5 <div className="space-y-3">
6 <Skeleton size="sm" className="w-40" />
7 <Skeleton size="md" className="w-56" />
8 <Skeleton size="lg" className="w-72" />
9 </div>
10)
11}

Card Loading$

Compose multiple skeletons to mirror real card layouts during async fetch.

TSX
1import { Skeleton } from "@glinui/ui"
2
3export function SkeletonCardDemo() {
4return (
5 <div className="max-w-sm rounded-2xl border border-neutral-200 p-4 dark:border-neutral-800">
6 <Skeleton className="h-40 w-full rounded-xl" />
7 <div className="mt-4 space-y-3">
8 <Skeleton className="h-5 w-3/4" />
9 <Skeleton className="h-4 w-full" />
10 <Skeleton className="h-4 w-5/6" />
11 </div>
12 <div className="mt-5 flex items-center gap-3">
13 <Skeleton className="h-9 w-9 rounded-full" />
14 <div className="space-y-2">
15 <Skeleton className="h-3.5 w-24" />
16 <Skeleton className="h-3 w-16" />
17 </div>
18 </div>
19 </div>
20)
21}

Profile Loading$

Avatar, name, and bio placeholders for a user profile state.

TSX
1import { Skeleton } from "@glinui/ui"
2
3export function SkeletonProfileDemo() {
4return (
5 <div className="flex items-start gap-4">
6 <Skeleton className="h-16 w-16 shrink-0 rounded-full" />
7 <div className="flex-1 space-y-3 pt-1">
8 <Skeleton className="h-5 w-40" />
9 <Skeleton className="h-3.5 w-56" />
10 <div className="flex gap-4 pt-1">
11 <Skeleton className="h-3 w-20" />
12 <Skeleton className="h-3 w-20" />
13 <Skeleton className="h-3 w-20" />
14 </div>
15 </div>
16 </div>
17)
18}

Media Grid$

Image grid placeholder for gallery or feed views.

TSX
1import { Skeleton } from "@glinui/ui"
2
3export function SkeletonMediaGridDemo() {
4return (
5 <div className="grid grid-cols-3 gap-3">
6 <Skeleton className="aspect-square w-full rounded-xl" />
7 <Skeleton className="aspect-square w-full rounded-xl" />
8 <Skeleton className="aspect-square w-full rounded-xl" />
9 <Skeleton className="col-span-2 aspect-video w-full rounded-xl" />
10 <Skeleton className="aspect-square w-full rounded-xl" />
11 </div>
12)
13}

Glass Card Loading$

Skeleton on a glass surface for overlay loading states.

TSX
1import { Skeleton } from "@glinui/ui"
2
3export function SkeletonGlassDemo() {
4return (
5 <div className="max-w-sm rounded-2xl border border-white/20 bg-white/30 p-5 backdrop-blur-xl dark:border-white/10 dark:bg-white/5">
6 <div className="flex items-center gap-3">
7 <Skeleton variant="glass" className="h-11 w-11 rounded-full" />
8 <div className="space-y-2 flex-1">
9 <Skeleton variant="glass" className="h-4 w-32" />
10 <Skeleton variant="glass" className="h-3 w-20" />
11 </div>
12 </div>
13 <div className="mt-4 space-y-2.5">
14 <Skeleton variant="glass" className="h-3.5 w-full" />
15 <Skeleton variant="glass" className="h-3.5 w-full" />
16 <Skeleton variant="glass" className="h-3.5 w-3/4" />
17 </div>
18 <div className="mt-4 flex gap-2">
19 <Skeleton variant="glass" className="h-9 w-24 rounded-xl" />
20 <Skeleton variant="glass" className="h-9 w-24 rounded-xl" />
21 </div>
22 </div>
23)
24}

List Loading$

Row-based skeleton for table or list views.

TSX
1import { Skeleton } from "@glinui/ui"
2
3export function SkeletonListDemo() {
4return (
5 <div className="max-w-md divide-y divide-neutral-200 dark:divide-neutral-800">
6 {[1, 2, 3, 4].map((i) => (
7 <div key={i} className="flex items-center gap-3 py-3">
8 <Skeleton className="h-10 w-10 shrink-0 rounded-lg" />
9 <div className="flex-1 space-y-2">
10 <Skeleton className="h-4 w-3/5" />
11 <Skeleton className="h-3 w-2/5" />
12 </div>
13 <Skeleton className="h-8 w-16 rounded-lg" />
14 </div>
15 ))}
16 </div>
17)
18}

Accessibility$

  • Decorative placeholders default to aria-hidden so screen readers skip them.
  • Set decorative={false} and add role="status" with aria-live="polite" for semantic loading regions.
  • Avoid stacking more than 5-6 skeletons without a loading boundary to limit screen reader noise.

Reduced Motion$

Shimmer animation uses motion-safe:animate-[...] / motion-reduce:hidden. Under prefers-reduced-motion, the shimmer overlay is hidden entirely and the skeleton renders as a static muted shape.

API Reference$

PropTypeRequiredDefaultDescription
decorativebooleanNotrueAuto-generated from TypeScript source.
size"sm" | "md" | "lg"No"md"Variant option from skeletonVariants.
variant"default" | "glass" | "liquid" | "matte" | "outline" | "ghost"No"default"Variant option from skeletonVariants.

Source$

TSX
1import { Skeleton } from "@glinui/ui"
packages/ui/src/components/skeleton.tsx
packages/ui/src/tests/skeleton.test.tsx

Generated API Snapshot

Beta

Auto-extracted from TypeScript source in packages/ui/src/components/skeleton.tsx. This section is in beta and may lag behind hand-curated docs. Regenerate with pnpm --filter @glinui/docs api:generate.

Generated: 2026-02-19T17:59:28.468Z · Full index: /docs/api-metadata

Primary Props Type

SkeletonProps

SkeletonProps

PropTypeRequiredDefaultDescription
decorativebooleanNotrue-
size"sm" | "md" | "lg"No"md"Variant option from skeletonVariants.
variant"default" | "glass" | "liquid" | "matte" | "outline" | "ghost"No"default"Variant option from skeletonVariants.