Skip to content

Skeleton

Skeleton

A placeholder component for loading content.

Import

import { Skeleton } from '@primitivekit/react';

Basic Usage

<Skeleton />

Variants

// Text (default)
<Skeleton variant="text" />

// Circle
<Skeleton variant="circle" width="50px" height="50px" />

// Rectangle
<Skeleton variant="rectangle" width="200px" height="100px" />

Sizes

<Skeleton width="100%" height="20px" />
<Skeleton width="80%" height="20px" />
<Skeleton width="60%" height="20px" />

Animation

// Pulse (default)
<Skeleton animation="pulse" />

// Wave
<Skeleton animation="wave" />

// None
<Skeleton animation="none" />

Multiple Lines

<div>
  <Skeleton width="100%" />
  <Skeleton width="90%" />
  <Skeleton width="80%" />
</div>

Props

PropTypeDefaultDescription
variant'text' | 'circle' | 'rectangle''text'Skeleton variant
widthstring | number'100%'Skeleton width
heightstring | number'1em'Skeleton height
animation'pulse' | 'wave' | 'none''pulse'Animation type
classNamestring-Additional CSS classes
styleSkeletonCSSVariables-CSS variable overrides

Customization

<Skeleton
  style={{
    '--skeleton-bg': 'rgba(230, 230, 230, 1)',
    '--skeleton-highlight': 'rgba(245, 245, 245, 1)',
    '--skeleton-border-radius': '8px',
  }}
/>

Examples

Card Skeleton

function CardSkeleton() {
  return (
    <Card>
      <Skeleton variant="rectangle" width="100%" height="200px" />
      <Skeleton width="80%" height="24px" style={{ marginTop: '16px' }} />
      <Skeleton width="60%" height="20px" />
      <Skeleton width="40%" height="20px" />
    </Card>
  );
}

Profile Skeleton

function ProfileSkeleton() {
  return (
    <div style={{ display: 'flex', gap: '16px' }}>
      <Skeleton variant="circle" width="60px" height="60px" />
      <div style={{ flex: 1 }}>
        <Skeleton width="40%" height="20px" />
        <Skeleton width="60%" height="16px" />
        <Skeleton width="80%" height="16px" />
      </div>
    </div>
  );
}

List Skeleton

function ListSkeleton({ count = 5 }) {
  return (
    <div>
      {Array.from({ length: count }).map((_, i) => (
        <div key={i} style={{ marginBottom: '16px' }}>
          <Skeleton width="100%" height="60px" />
        </div>
      ))}
    </div>
  );
}

Conditional Loading

function UserProfile({ loading, user }) {
  if (loading) {
    return <ProfileSkeleton />;
  }

  return (
    <div>
      <Avatar src={user.avatar} />
      <h3>{user.name}</h3>
      <p>{user.bio}</p>
    </div>
  );
}

Accessibility

  • ✅ ARIA role=“status”
  • ✅ aria-busy attribute
  • ✅ Screen reader announcements
  • ✅ Proper loading states

Related Components