Placeholder/Skeleton
The Placeholder/Skeleton components provide loading states and content placeholders for better user experience. They include individual skeleton elements, skeleton cards, skeleton lists, and skeleton forms that mimic the structure of actual content while data is loading.
Overview
The Placeholder/Skeleton components are designed to provide engaging loading states with:
- Individual skeleton elements with various shapes and sizes
- Pre-built skeleton cards for different content types
- Skeleton lists for list-based content
- Skeleton forms for form loading states
- Customizable animations and styling
- Dark mode support
- Responsive design
Basic Usage
import { Skeleton } from '@/components/atoms'
import { SkeletonCard, SkeletonList, SkeletonForm } from '@/components/molecules'
function MyComponent() {
return (
<div className='space-y-4'>
{/* Basic skeleton */}
<Skeleton variant='text' width='w-full' height='h-4' />
{/* Skeleton card */}
<SkeletonCard variant='default' lines={3} />
{/* Skeleton list */}
<SkeletonList items={5} variant='default' showAvatar={true} />
{/* Skeleton form */}
<SkeletonForm fields={4} showTitle={true} showButtons={true} />
</div>
)
}
Skeleton Component
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | string | 'text' | Shape variant ('text', 'circle', 'rectangle', 'avatar', 'button') |
className | string | '' | Additional CSS classes |
width | string | 'w-full' | Width CSS class |
height | string | 'h-4' | Height CSS class |
rounded | string | 'rounded' | Border radius CSS class |
animated | boolean | true | Whether to show pulse animation |
Basic Skeleton
<Card>
<h4 className='mb-4'>Basic Skeleton</h4>
<div className='space-y-3'>
<Skeleton variant='text' width='w-full' height='h-4' />
<Skeleton variant='text' width='w-3/4' height='h-4' />
<Skeleton variant='text' width='w-1/2' height='h-4' />
</div>
</Card>
Skeleton with Avatar
<Card>
<h4 className='mb-4'>Skeleton with Avatar</h4>
<div className='flex items-center gap-4'>
<Skeleton variant='avatar' width='w-12' height='h-12' />
<div className='flex-1 space-y-2'>
<Skeleton variant='text' width='w-1/2' height='h-4' />
<Skeleton variant='text' width='w-3/4' height='h-3' />
</div>
</div>
</Card>
Skeleton Shapes
<Card>
<h4 className='mb-4'>Skeleton Shapes</h4>
<div className='space-y-4'>
<div className='flex items-center gap-4'>
<Skeleton variant='circle' width='w-8' height='h-8' />
<span className='text-sm text-gray-500'>Circle</span>
</div>
<div className='flex items-center gap-4'>
<Skeleton variant='rectangle' width='w-16' height='h-8' />
<span className='text-sm text-gray-500'>Rectangle</span>
</div>
<div className='flex items-center gap-4'>
<Skeleton variant='button' width='w-24' height='h-8' />
<span className='text-sm text-gray-500'>Button</span>
</div>
</div>
</Card>
Custom Sizes
<Card>
<h4 className='mb-4'>Skeleton with Custom Sizes</h4>
<div className='space-y-3'>
<Skeleton variant='text' width='w-32' height='h-2' />
<Skeleton variant='text' width='w-48' height='h-4' />
<Skeleton variant='text' width='w-64' height='h-6' />
<Skeleton variant='text' width='w-40' height='h-8' />
</div>
</Card>
Without Animation
<Card>
<h4 className='mb-4'>Skeleton without Animation</h4>
<div className='space-y-3'>
<Skeleton variant='text' width='w-full' height='h-4' animated={false} />
<Skeleton variant='text' width='w-3/4' height='h-4' animated={false} />
<Skeleton variant='text' width='w-1/2' height='h-4' animated={false} />
</div>
</Card>
SkeletonCard Component
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | string | 'default' | Card variant ('default', 'article', 'profile', 'table') |
className | string | '' | Additional CSS classes |
showImage | boolean | false | Whether to show image skeleton |
showAvatar | boolean | false | Whether to show avatar skeleton |
lines | number | 3 | Number of text lines (default variant only) |
Default Card
<Card>
<h4 className='mb-4'>Skeleton Card - Default</h4>
<SkeletonCard variant='default' lines={4} />
</Card>
Article Card
<Card>
<h4 className='mb-4'>Skeleton Card - Article</h4>
<SkeletonCard variant='article' showImage={true} />
</Card>
Profile Card
<Card>
<h4 className='mb-4'>Skeleton Card - Profile</h4>
<SkeletonCard variant='profile' />
</Card>
Table Card
<Card>
<h4 className='mb-4'>Skeleton Card - Table</h4>
<SkeletonCard variant='table' showAvatar={true} />
</Card>
Card with Image
<Card>
<h4 className='mb-4'>Skeleton Card with Image</h4>
<SkeletonCard variant='default' showImage={true} lines={3} />
</Card>
Card with Avatar
<Card>
<h4 className='mb-4'>Skeleton Card with Avatar</h4>
<SkeletonCard variant='default' showAvatar={true} lines={3} />
</Card>
SkeletonList Component
Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | number | 5 | Number of list items |
variant | string | 'default' | List variant ('default', 'compact', 'detailed') |
showAvatar | boolean | false | Whether to show avatar skeletons |
showImage | boolean | false | Whether to show image skeletons |
className | string | '' | Additional CSS classes |
Default List
<Card>
<h4 className='mb-4'>Skeleton List - Default</h4>
<SkeletonList items={3} variant='default' showAvatar={true} />
</Card>
Compact List
<Card>
<h4 className='mb-4'>Skeleton List - Compact</h4>
<SkeletonList items={5} variant='compact' showAvatar={true} />
</Card>
Detailed List
<Card>
<h4 className='mb-4'>Skeleton List - Detailed</h4>
<SkeletonList items={3} variant='detailed' showAvatar={true} showImage={true} />
</Card>
List with Avatars
<Card>
<h4 className='mb-4'>Skeleton List with Avatars</h4>
<SkeletonList items={4} variant='default' showAvatar={true} />
</Card>
List with Images
<Card>
<h4 className='mb-4'>Skeleton List with Images</h4>
<SkeletonList items={3} variant='detailed' showAvatar={true} showImage={true} />
</Card>
SkeletonForm Component
Props
| Prop | Type | Default | Description |
|---|---|---|---|
fields | number | 4 | Number of form fields |
showTitle | boolean | true | Whether to show title skeleton |
showButtons | boolean | true | Whether to show button skeletons |
className | string | '' | Additional CSS classes |
Complete Form
<Card>
<h4 className='mb-4'>Skeleton Form</h4>
<SkeletonForm fields={5} showTitle={true} showButtons={true} />
</Card>
Form without Title
<Card>
<h4 className='mb-4'>Skeleton Form - No Title</h4>
<SkeletonForm fields={3} showTitle={false} showButtons={true} />
</Card>
Form without Buttons
<Card>
<h4 className='mb-4'>Skeleton Form - No Buttons</h4>
<SkeletonForm fields={4} showTitle={true} showButtons={false} />
</Card>
Minimal Form
<Card>
<h4 className='mb-4'>Minimal Skeleton Form</h4>
<SkeletonForm fields={2} showTitle={false} showButtons={false} />
</Card>
Advanced Examples
Skeleton Grid
<Card>
<h4 className='mb-4'>Skeleton Grid</h4>
<div className='grid grid-cols-2 gap-4'>
<SkeletonCard variant='default' lines={2} />
<SkeletonCard variant='default' lines={2} />
<SkeletonCard variant='default' lines={2} />
<SkeletonCard variant='default' lines={2} />
</div>
</Card>
Mixed Content Layout
<Card>
<h4 className='mb-4'>Mixed Content Layout</h4>
<div className='space-y-6'>
{/* Header */}
<div className='flex items-center gap-4'>
<Skeleton variant='avatar' width='w-16' height='h-16' />
<div className='flex-1 space-y-2'>
<Skeleton variant='text' width='w-1/3' height='h-6' />
<Skeleton variant='text' width='w-1/2' height='h-4' />
</div>
</div>
{/* Content */}
<div className='space-y-3'>
<Skeleton variant='text' width='w-full' height='h-4' />
<Skeleton variant='text' width='w-5/6' height='h-4' />
<Skeleton variant='text' width='w-4/6' height='h-4' />
</div>
{/* Actions */}
<div className='flex gap-3'>
<Skeleton variant='button' width='w-24' height='h-10' />
<Skeleton variant='button' width='w-24' height='h-10' />
</div>
</div>
</Card>
Dashboard Layout
<Card>
<h4 className='mb-4'>Dashboard Layout</h4>
<div className='space-y-6'>
{/* Stats Row */}
<div className='grid grid-cols-4 gap-4'>
{[...Array(4)].map((_, index) => (
<div key={index} className='space-y-2'>
<Skeleton variant='text' width='w-16' height='h-4' />
<Skeleton variant='text' width='w-24' height='h-8' />
</div>
))}
</div>
{/* Content Area */}
<div className='grid grid-cols-2 gap-6'>
<SkeletonCard variant='default' lines={4} />
<SkeletonList items={3} variant='compact' showAvatar={true} />
</div>
</div>
</Card>
Examples
Basic Skeleton
<Card>
<h4 className='mb-4'>Basic Skeleton</h4>
<div className='space-y-3'>
<Skeleton variant='text' width='w-full' height='h-4' />
<Skeleton variant='text' width='w-3/4' height='h-4' />
<Skeleton variant='text' width='w-1/2' height='h-4' />
</div>
</Card>
Skeleton with Avatar
<Card>
<h4 className='mb-4'>Skeleton with Avatar</h4>
<div className='flex items-center gap-4'>
<Skeleton variant='avatar' width='w-12' height='h-12' />
<div className='flex-1 space-y-2'>
<Skeleton variant='text' width='w-1/2' height='h-4' />
<Skeleton variant='text' width='w-3/4' height='h-3' />
</div>
</div>
</Card>
Skeleton Card - Default
<Card>
<h4 className='mb-4'>Skeleton Card - Default</h4>
<SkeletonCard variant='default' lines={4} />
</Card>
Skeleton Card - Article
<Card>
<h4 className='mb-4'>Skeleton Card - Article</h4>
<SkeletonCard variant='article' showImage={true} />
</Card>
Skeleton Card - Profile
<Card>
<h4 className='mb-4'>Skeleton Card - Profile</h4>
<SkeletonCard variant='profile' />
</Card>
Skeleton Card - Table
<Card>
<h4 className='mb-4'>Skeleton Card - Table</h4>
<SkeletonCard variant='table' showAvatar={true} />
</Card>
Skeleton List - Default
<Card>
<h4 className='mb-4'>Skeleton List - Default</h4>
<SkeletonList items={3} variant='default' showAvatar={true} />
</Card>
Skeleton List - Compact
<Card>
<h4 className='mb-4'>Skeleton List - Compact</h4>
<SkeletonList items={5} variant='compact' showAvatar={true} />
</Card>
Skeleton List - Detailed
<Card>
<h4 className='mb-4'>Skeleton List - Detailed</h4>
<SkeletonList items={3} variant='detailed' showAvatar={true} showImage={true} />
</Card>
Skeleton Shapes
<Card>
<h4 className='mb-4'>Skeleton Shapes</h4>
<div className='space-y-4'>
<div className='flex items-center gap-4'>
<Skeleton variant='circle' width='w-8' height='h-8' />
<span className='text-sm text-gray-500'>Circle</span>
</div>
<div className='flex items-center gap-4'>
<Skeleton variant='rectangle' width='w-16' height='h-8' />
<span className='text-sm text-gray-500'>Rectangle</span>
</div>
<div className='flex items-center gap-4'>
<Skeleton variant='button' width='w-24' height='h-8' />
<span className='text-sm text-gray-500'>Button</span>
</div>
</div>
</Card>
Skeleton with Custom Sizes
<Card>
<h4 className='mb-4'>Skeleton with Custom Sizes</h4>
<div className='space-y-3'>
<Skeleton variant='text' width='w-32' height='h-2' />
<Skeleton variant='text' width='w-48' height='h-4' />
<Skeleton variant='text' width='w-64' height='h-6' />
<Skeleton variant='text' width='w-40' height='h-8' />
</div>
</Card>
Skeleton Grid
<Card>
<h4 className='mb-4'>Skeleton Grid</h4>
<div className='grid grid-cols-2 gap-4'>
<SkeletonCard variant='default' lines={2} />
<SkeletonCard variant='default' lines={2} />
<SkeletonCard variant='default' lines={2} />
<SkeletonCard variant='default' lines={2} />
</div>
</Card>
Skeleton without Animation
<Card>
<h4 className='mb-4'>Skeleton without Animation</h4>
<div className='space-y-3'>
<Skeleton variant='text' width='w-full' height='h-4' animated={false} />
<Skeleton variant='text' width='w-3/4' height='h-4' animated={false} />
<Skeleton variant='text' width='w-1/2' height='h-4' animated={false} />
</div>
</Card>
Skeleton Form
<Card>
<h4 className='mb-4'>Skeleton Form</h4>
<SkeletonForm fields={5} showTitle={true} showButtons={true} />
</Card>
Skeleton Form - No Title
<Card>
<h4 className='mb-4'>Skeleton Form - No Title</h4>
<SkeletonForm fields={3} showTitle={false} showButtons={true} />
</Card>
Skeleton Form - No Buttons
<Card>
<h4 className='mb-4'>Skeleton Form - No Buttons</h4>
<SkeletonForm fields={4} showTitle={true} showButtons={false} />
</Card>
CSS Classes Reference
Skeleton Base
.bg-gray-200- Light gray background.dark:bg-gray-700- Dark mode background.animate-pulse- Pulse animation
Skeleton Variants
text- Text line skeletoncircle- Circular skeletonrectangle- Rectangular skeletonavatar- Avatar skeletonbutton- Button skeleton
SkeletonCard
.skeleton-card- Base card container.bg-white- Card background.dark:bg-gray-800- Dark mode card background.rounded-lg- Rounded corners.p-6- Padding.shadow-sm- Subtle shadow
SkeletonList
.skeleton-list- Base list container.space-y-4- Vertical spacing between items.skeleton-item- Individual list item
SkeletonForm
.skeleton-form- Base form container.space-y-6- Vertical spacing between sections.space-y-4- Vertical spacing between fields.space-y-2- Vertical spacing between elements
Styling
The Placeholder/Skeleton components use Tailwind CSS classes and include:
- Gray Backgrounds: Consistent skeleton colors
- Dark Mode Support: Automatic dark mode variants
- Pulse Animation: Smooth loading animation
- Responsive Design: Works on all screen sizes
- Flexible Sizing: Customizable width and height
- Border Radius: Configurable rounded corners
- Spacing: Consistent spacing patterns
Accessibility
The Placeholder/Skeleton components include accessibility features:
- Semantic Structure: Proper HTML structure
- Screen Reader Support: Non-interactive elements
- Color Contrast: Proper contrast ratios
- Animation Control: Optional animations
- Focus Management: Non-focusable elements
Best Practices
- Use appropriate variants for your content type
- Match skeleton structure to actual content layout
- Consider animation preferences for users
- Use consistent sizing with actual content
- Provide meaningful context with skeleton titles
- Test with screen readers for accessibility
Common Use Cases
- Content loading: Show while data is being fetched
- List placeholders: Maintain layout during loading
- Form placeholders: Show form structure before data loads
- Card placeholders: Maintain card layout consistency
- Dashboard loading: Show dashboard structure during initialization
Related Components
Skeleton- Individual skeleton elementSkeletonCard- Pre-built skeleton cardsSkeletonList- Skeleton list layoutsSkeletonForm- Skeleton form layoutsCard- Often used as a container for skeleton examples