Skip to main content

Overview

Skeleton replaces real content during loading to reduce perceived wait time and prevent layout shift. It animates with a shimmer effect and can be composed into any layout using predefined shape variants.

Installation

npm install @araf-ds/core

Usage

import { Skeleton } from "@araf-ds/core"

function UserCard({ loading, user }) {
  if (loading) {
    return (
      <div className="p-4 space-y-3">
        <div className="flex items-center gap-3">
          <Skeleton variant="circular" width={40} height={40} />
          <div className="flex-1 space-y-1">
            <Skeleton variant="text" lines={1} width="50%" />
            <Skeleton variant="text" lines={1} width="35%" />
          </div>
        </div>
        <Skeleton variant="text" lines={2} />
      </div>
    )
  }
  return <UserCardContent user={user} />
}

Variants

Text Lines

<Skeleton variant="text" lines={3} />

Avatar Placeholder

<Skeleton variant="circular" width={40} height={40} />
<Skeleton variant="circular" width={48} height={48} />
<Skeleton variant="circular" width={64} height={64} />

Card Placeholder

<div className="flex items-center gap-4">
  <Skeleton variant="circular" width={48} height={48} />
  <div className="flex-1 space-y-2">
    <Skeleton variant="text" lines={1} width="60%" />
    <Skeleton variant="text" lines={1} width="40%" />
  </div>
</div>

Image Placeholder

<Skeleton variant="rectangular" height={200} />

Table Row Placeholder

{Array.from({ length: 5 }).map((_, i) => (
  <div key={i} className="flex gap-4 py-3">
    <Skeleton width={32} height={32} variant="circular" />
    <Skeleton variant="text" lines={1} width="30%" />
    <Skeleton variant="rounded" width={60} height={22} />
  </div>
))}

API Reference

variant
string
default:"rounded"
Shape of the skeleton. Values: text · circular · rectangular · rounded
width
string | number
default:"100%"
Width as a CSS value ("60%") or pixel number (240).
height
string | number
Height as a CSS value or pixel number. Required for non-text variants.
lines
number
For text variant: number of text line skeletons to render.
animate
boolean
default:"true"
Enables the shimmer animation.
className
string
Additional Tailwind classes for custom overrides.

Accessibility

  • Skeleton containers use aria-busy="true" and aria-label="Loading" to announce loading state
  • When content loads, aria-busy is removed so screen readers announce the real content
  • Do not use Skeleton for content that loads instantly (under 300ms) — it adds unnecessary visual noise
  • Provide a text fallback for screen readers that cannot convey the loading state visually

Do’s & Don’ts

Do

  • Mirror the exact shape and size of the real content
  • Use Skeleton for content that takes longer than 300ms to load
  • Compose multiple Skeleton elements to build realistic loading screens
  • Disable animation (animate={false}) in reduced motion environments

Don't

  • Don’t use Skeleton for content that loads instantly — use a spinner instead
  • Don’t add Skeleton for every element — focus on primary content
  • Don’t mix Skeleton with real content in the same card
  • Don’t display Skeleton indefinitely — show an error state if loading fails