> ## Documentation Index
> Fetch the complete documentation index at: https://araf.badr.co.id/llms.txt
> Use this file to discover all available pages before exploring further.

# Skeleton

> A placeholder loading state that mimics the shape of content before it loads — reduces perceived wait time with a shimmer animation.

## Overview

<div style={{padding:"28px 24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{display:"flex",flexDirection:"column",gap:"20px"}}>
    <div style={{display:"flex",alignItems:"center",gap:"12px"}}>
      <div style={{width:"40px",height:"40px",borderRadius:"50%",background:"linear-gradient(90deg, #E5E7EB 25%, #F3F4F6 50%, #E5E7EB 75%)",backgroundSize:"200% 100%",flexShrink:0}} />

      <div style={{flex:1,display:"flex",flexDirection:"column",gap:"8px"}}>
        <div style={{height:"12px",background:"linear-gradient(90deg, #E5E7EB 25%, #F3F4F6 50%, #E5E7EB 75%)",borderRadius:"4px",width:"50%"}} />

        <div style={{height:"12px",background:"linear-gradient(90deg, #E5E7EB 25%, #F3F4F6 50%, #E5E7EB 75%)",borderRadius:"4px",width:"35%"}} />
      </div>
    </div>

    <div style={{display:"flex",flexDirection:"column",gap:"8px"}}>
      <div style={{height:"12px",background:"linear-gradient(90deg, #E5E7EB 25%, #F3F4F6 50%, #E5E7EB 75%)",borderRadius:"4px"}} />

      <div style={{height:"12px",background:"linear-gradient(90deg, #E5E7EB 25%, #F3F4F6 50%, #E5E7EB 75%)",borderRadius:"4px"}} />

      <div style={{height:"12px",background:"linear-gradient(90deg, #E5E7EB 25%, #F3F4F6 50%, #E5E7EB 75%)",borderRadius:"4px",width:"75%"}} />
    </div>

    <div style={{height:"120px",background:"linear-gradient(90deg, #E5E7EB 25%, #F3F4F6 50%, #E5E7EB 75%)",borderRadius:"8px"}} />
  </div>
</div>

**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

<CodeGroup>
  ```bash npm theme={null}
  npm install @araf-ds/core
  ```

  ```bash yarn theme={null}
  yarn add @araf-ds/core
  ```

  ```bash pnpm theme={null}
  pnpm add @araf-ds/core
  ```
</CodeGroup>

***

## Usage

```tsx theme={null}
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

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{display:"flex",flexDirection:"column",gap:"8px",maxWidth:"320px"}}>
    <div style={{height:"12px",background:"#E5E7EB",borderRadius:"4px"}} />

    <div style={{height:"12px",background:"#E5E7EB",borderRadius:"4px"}} />

    <div style={{height:"12px",background:"#E5E7EB",borderRadius:"4px",width:"75%"}} />
  </div>
</div>

```tsx theme={null}
<Skeleton variant="text" lines={3} />
```

### Avatar Placeholder

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb",display:"flex",gap:"12px",alignItems:"center"}}>
  <div style={{width:"40px",height:"40px",borderRadius:"50%",background:"#E5E7EB",flexShrink:0}} />

  <div style={{width:"48px",height:"48px",borderRadius:"50%",background:"#E5E7EB",flexShrink:0}} />

  <div style={{width:"64px",height:"64px",borderRadius:"50%",background:"#E5E7EB",flexShrink:0}} />
</div>

```tsx theme={null}
<Skeleton variant="circular" width={40} height={40} />
<Skeleton variant="circular" width={48} height={48} />
<Skeleton variant="circular" width={64} height={64} />
```

### Card Placeholder

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{display:"flex",alignItems:"center",gap:"12px",maxWidth:"320px"}}>
    <div style={{width:"48px",height:"48px",borderRadius:"50%",background:"#E5E7EB",flexShrink:0}} />

    <div style={{flex:1,display:"flex",flexDirection:"column",gap:"8px"}}>
      <div style={{height:"12px",background:"#E5E7EB",borderRadius:"4px",width:"60%"}} />

      <div style={{height:"12px",background:"#E5E7EB",borderRadius:"4px",width:"40%"}} />
    </div>
  </div>
</div>

```tsx theme={null}
<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

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{height:"120px",background:"#E5E7EB",borderRadius:"8px",maxWidth:"320px"}} />
</div>

```tsx theme={null}
<Skeleton variant="rectangular" height={200} />
```

### Table Row Placeholder

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{display:"flex",flexDirection:"column",gap:"12px",maxWidth:"400px"}}>
    {[1,2,3].map((i) => (
            <div key={i} style={{display:"flex",alignItems:"center",gap:"12px"}}>
              <div style={{width:"32px",height:"32px",borderRadius:"50%",background:"#E5E7EB",flexShrink:0}}/>
              <div style={{width:"30%",height:"12px",background:"#E5E7EB",borderRadius:"4px"}}/>
              <div style={{width:"60px",height:"22px",background:"#E5E7EB",borderRadius:"12px"}}/>
            </div>
          ))}
  </div>
</div>

```tsx theme={null}
{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

<ParamField path="variant" type="string" default="rounded">
  Shape of the skeleton. Values: `text` · `circular` · `rectangular` · `rounded`
</ParamField>

<ParamField path="width" type="string | number" default="100%">
  Width as a CSS value (`"60%"`) or pixel number (`240`).
</ParamField>

<ParamField path="height" type="string | number">
  Height as a CSS value or pixel number. Required for non-text variants.
</ParamField>

<ParamField path="lines" type="number">
  For `text` variant: number of text line skeletons to render.
</ParamField>

<ParamField path="animate" type="boolean" default="true">
  Enables the shimmer animation.
</ParamField>

<ParamField path="className" type="string">
  Additional Tailwind classes for custom overrides.
</ParamField>

***

## 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

<CardGroup cols={2}>
  <Card title="Do" icon="check" iconType="solid" color="#16A34A">
    * 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
  </Card>

  <Card title="Don't" icon="xmark" iconType="solid" color="#DC2626">
    * 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
  </Card>
</CardGroup>
