Introduction
Components
- Accordion
- Action Sheet
- Alert
- Audio Player
- Audio Recorder
- Audio Waveform
- Avatar
- Badge
- BottomSheet
- Button
- Camera
- Camera Preview
- Card
- Carousel
- Checkbox
- Collapsible
- Color Picker
- Combobox
- Date Picker
- File Picker
- Gallery
- Hello Wave
- Icon
- Image
- Input
- Input OTP
- Link
- MediaPicker
- Mode Toggle
- Onboarding
- ParallaxScrollView
- Picker
- Popover
- Progress
- Radio
- ScrollView
- SearchBar
- Separator
- Share
- Sheet
- Skeleton
- Spinner
- Switch
- Table
- Tabs
- Text
- Toast
- Toggle
- Video
- View
Charts
import { Skeleton } from '@/components/ui/skeleton';
import React from 'react';
export function SkeletonDemo() {
return <Skeleton width={200} height={20} />;
}
Installation
pnpm dlx bna-ui add skeleton
Usage
import { Skeleton } from '@/components/ui/skeleton';
<Skeleton width={200} height={20} />
Examples
Default
import { Skeleton } from '@/components/ui/skeleton';
import React from 'react';
export function SkeletonDemo() {
return <Skeleton width={200} height={20} />;
}
Different Sizes
import { Skeleton } from '@/components/ui/skeleton';
import { View } from '@/components/ui/view';
import React from 'react';
export function SkeletonSizes() {
return (
<View style={{ gap: 12 }}>
<Skeleton width={100} height={16} />
<Skeleton width={200} height={20} />
<Skeleton width={300} height={24} />
<Skeleton width='100%' height={32} />
</View>
);
}
Card Layout
import { Skeleton } from '@/components/ui/skeleton';
import { View } from '@/components/ui/view';
import { useThemeColor } from '@/hooks/useThemeColor';
import { BORDER_RADIUS } from '@/theme/globals';
import React from 'react';
export function SkeletonCard() {
const card = useThemeColor({}, 'card');
return (
<View
style={{
padding: 16,
borderRadius: BORDER_RADIUS,
backgroundColor: card,
gap: 12,
}}
>
{/* Header */}
<View style={{ flexDirection: 'row', gap: 12, alignItems: 'center' }}>
<Skeleton width={40} height={40} style={{ borderRadius: 20 }} />
<View style={{ flex: 1, gap: 4 }}>
<Skeleton width='60%' height={16} />
<Skeleton width='40%' height={12} />
</View>
</View>
{/* Content */}
<Skeleton width='100%' height={200} variant='rounded' />
{/* Footer */}
<View style={{ gap: 8 }}>
<Skeleton width='100%' height={16} />
<Skeleton width='80%' height={16} />
<Skeleton width='60%' height={16} />
</View>
</View>
);
}
Profile Layout
import { Skeleton } from '@/components/ui/skeleton';
import { View } from '@/components/ui/view';
import { useThemeColor } from '@/hooks/useThemeColor';
import { BORDER_RADIUS } from '@/theme/globals';
import React from 'react';
export function SkeletonProfile() {
const card = useThemeColor({}, 'card');
return (
<View
style={{
alignItems: 'center',
gap: 16,
padding: 16,
borderRadius: BORDER_RADIUS,
backgroundColor: card,
}}
>
{/* Profile Picture */}
<Skeleton width={80} height={80} style={{ borderRadius: 40 }} />
{/* Name and Title */}
<View style={{ alignItems: 'center', gap: 8 }}>
<Skeleton width={150} height={20} />
<Skeleton width={100} height={16} />
</View>
{/* Stats */}
<View style={{ flexDirection: 'row', gap: 24 }}>
<View style={{ alignItems: 'center', gap: 4 }}>
<Skeleton width={30} height={18} />
<Skeleton width={50} height={14} />
</View>
<View style={{ alignItems: 'center', gap: 4 }}>
<Skeleton width={30} height={18} />
<Skeleton width={50} height={14} />
</View>
<View style={{ alignItems: 'center', gap: 4 }}>
<Skeleton width={30} height={18} />
<Skeleton width={50} height={14} />
</View>
</View>
{/* Bio */}
<View style={{ gap: 8, width: '100%' }}>
<Skeleton width='100%' height={16} />
<Skeleton width='90%' height={16} />
<Skeleton width='70%' height={16} />
</View>
</View>
);
}
List Items
import { Skeleton } from '@/components/ui/skeleton';
import { View } from '@/components/ui/view';
import { useThemeColor } from '@/hooks/useThemeColor';
import { BORDER_RADIUS } from '@/theme/globals';
import React from 'react';
export function SkeletonList() {
const card = useThemeColor({}, 'card');
return (
<View
style={{
gap: 16,
padding: 16,
borderRadius: BORDER_RADIUS,
backgroundColor: card,
}}
>
{Array.from({ length: 5 }, (_, i) => (
<View
key={i}
style={{ flexDirection: 'row', gap: 12, alignItems: 'center' }}
>
<Skeleton width={50} height={50} style={{ borderRadius: 25 }} />
<View style={{ flex: 1, gap: 6 }}>
<Skeleton width='70%' height={16} />
<Skeleton width='50%' height={14} />
<Skeleton width='30%' height={12} />
</View>
</View>
))}
</View>
);
}
Custom Shapes
import { Skeleton } from '@/components/ui/skeleton';
import { View } from '@/components/ui/view';
import { useThemeColor } from '@/hooks/useThemeColor';
import { BORDER_RADIUS } from '@/theme/globals';
import React from 'react';
export function SkeletonShapes() {
const card = useThemeColor({}, 'card');
return (
<View
style={{
flexDirection: 'row',
flexWrap: 'wrap',
gap: 16,
padding: 16,
borderRadius: BORDER_RADIUS,
backgroundColor: card,
}}
>
{/* Circle */}
<Skeleton width={60} height={60} style={{ borderRadius: 30 }} />
{/* Square */}
<Skeleton width={60} height={60} style={{ borderRadius: 4 }} />
{/* Rounded Rectangle */}
<Skeleton width={120} height={60} style={{ borderRadius: 12 }} />
{/* Pill */}
<Skeleton width={100} height={30} style={{ borderRadius: 15 }} />
{/* Custom styled */}
<Skeleton
width={80}
height={80}
style={{
borderRadius: 20,
transform: [{ rotate: '45deg' }],
}}
/>
</View>
);
}
API Reference
Skeleton
A loading placeholder component with animated pulsing effect.
Prop | Type | Default | Description |
---|---|---|---|
width | number | string | 100% | The width of the skeleton. |
height | number | 100 | The height of the skeleton in pixels. |
style | ViewStyle | - | Additional styles to apply to the skeleton. |
Accessibility
The Skeleton component is built with accessibility in mind:
- Uses appropriate color contrast for loading states
- Provides visual feedback during content loading
- Maintains layout stability while content loads
- Compatible with screen readers through proper semantic structure