react-native-smart-skeleton
v0.0.4
Published
A fully customizable, theme-aware, animated skeleton loader for React Native.
Maintainers
Readme
react-native-smart-skeleton
A fully customizable, theme-aware, animated skeleton loader for React Native, powered by react-native-reanimated.
Created by Neeraj Singh.
Demo

Why use this package?
- Build fast, polished loading placeholders for React Native apps
- Support light/dark themes out of the box
- Use shimmer, pulse, wave, breathing, and none animations
- Customize colors, sizes, spacing, and performance mode
- Works well for cards, profiles, chats, products, and video screens
Overview
react-native-smart-skeleton is a lightweight, customizable skeleton loading library for React Native applications. It helps you create beautiful loading states with minimal code while staying accessible and theme-aware.
Features
- Auto light/dark theme detection (
useColorScheme, overridable viaSkeletonProvider) - Global
SkeletonProviderfor app-wide defaults - Shimmer, Pulse, Wave, and Breathing animations
- RTL-aware shimmer/wave sweep direction
- Accessibility support (
accessibilityRole="image", busy state, customizable labels) - Automatic reduced-motion fallback (OS setting or explicit override)
- Dynamic shape builder via
SkeletonClone(clone an arbitrary layout tree) - Smart presets:
Profile,Card,Chat,Product,Video - Responsive helpers for grid columns / size scaling
- Brand color support (named light/dark palettes)
- Performance modes (
high/balanced/battery-saver) Skeleton.Groupfor automatic stagger animations- Full TypeScript support
Installation
Install from npm
React Native CLI:
npm install react-native-smart-skeleton react-native-reanimated react-native-linear-gradientExpo:
npx expo install react-native-smart-skeleton react-native-reanimated expo-linear-gradientYarn:
yarn add react-native-smart-skeleton react-native-reanimated react-native-linear-gradientReact Native CLI apps may also need native linking and pods:
cd ios && pod install && cd ..Install from a local tarball
If you want to test this package locally from a built tarball:
cd /path/to/react-native-smart-skeleton
npm packThen install it into another app:
npm install /path/to/react-native-smart-skeleton/react-native-smart-skeleton-0.1.0.tgzIf the app is a sibling folder, the relative form is:
npm install ../react-native-smart-skeleton/react-native-smart-skeleton-0.1.0.tgzImport in both environments
The import is the same in Expo and React Native CLI:
import { SkeletonProvider, Skeleton } from "react-native-smart-skeleton";This package automatically uses expo-linear-gradient in Expo apps and react-native-linear-gradient in React Native CLI apps.
Follow the installation instructions for react-native-reanimated (Babel plugin) and either react-native-linear-gradient for React Native CLI or expo-linear-gradient for Expo.
Basic usage
import { SkeletonProvider, Skeleton } from "react-native-smart-skeleton";
export default function App() {
return (
<SkeletonProvider theme="system" animation="shimmer">
<Skeleton.Rect width={200} height={20} />
<Skeleton.Circle size={48} />
<Skeleton.Pill width={80} height={28} />
</SkeletonProvider>
);
}SkeletonProvider is optional — every shape also works standalone, falling back to the OS color scheme and library defaults.
Example usage
<SkeletonProvider
theme="system"
animation="shimmer"
performanceMode="balanced"
>
<SafeAreaView style={styles.container}>
<ScrollView
contentContainerStyle={styles.content}
showsVerticalScrollIndicator={false}
>
<Skeleton.Rect width={220} height={32} borderRadius={8} style={styles.spacing} />
<Skeleton.Rect
width="70%"
height={18}
borderRadius={6}
style={styles.spacing}
backgroundColor="rgb(116, 84, 84)"
highlightColor="#70cbe9"
/>
<Skeleton.Group staggerDelay={100}>
<Skeleton.Circle
size={80}
style={styles.avatar}
backgroundColor="rgb(185, 162, 162)"
highlightColor="#fff"
/>
<Skeleton.Rect
width="80%"
height={18}
style={styles.smallSpacing}
backgroundColor="rgb(213, 20, 20)"
highlightColor="#fff"
/>
<Skeleton.Rect
width="60%"
height={18}
style={styles.spacing}
backgroundColor="rgb(185, 162, 162)"
highlightColor="#fff"
/>
</Skeleton.Group>
<Skeleton.Rect width="100%" height={120} borderRadius={12} style={styles.spacing} />
<Skeleton.Pill
width={140}
height={40}
style={styles.spacing}
backgroundColor="rgb(249, 96, 234)"
highlightColor="#edcff4"
/>
<Skeleton.Square size={80} borderRadius={12} style={styles.spacing} />
<Skeleton.Rect width="100%" height={18} animation="shimmer" style={styles.smallSpacing} />
<Skeleton.Rect width="100%" height={18} animation="pulse" style={styles.smallSpacing} />
<Skeleton.Rect width="100%" height={18} animation="wave" style={styles.smallSpacing} />
<Skeleton.Rect width="100%" height={18} animation="breathing" style={styles.spacing} />
<Skeleton.Profile avatarSize={60} lines={3} style={styles.spacing} />
<Skeleton.Card imageHeight={180} lines={3} showAvatar style={styles.spacing} />
<Skeleton.Chat messages={5} style={styles.spacing} />
<Skeleton.Product count={4} columns={2} style={styles.spacing} />
<Skeleton.Video aspectRatio={16 / 9} showTitle showMeta style={styles.spacing} />
<Skeleton.Clone
layout={{
direction: "row",
gap: 12,
children: [
{
shape: "circle",
width: 60,
height: 60,
},
{
direction: "column",
gap: 8,
children: [
{ width: 180, height: 16 },
{ width: 120, height: 14 },
{ width: 80, height: 14 },
],
},
],
}}
/>
</ScrollView>
</SafeAreaView>
</SkeletonProvider>Shapes
<Skeleton.Rect width={200} height={20} borderRadius={6} />
<Skeleton.Circle size={48} />
<Skeleton.Square size={64} borderRadius={8} />
<Skeleton.Pill width={100} height={32} />All shapes accept every prop from the base SkeletonProps: animation, duration, delay, backgroundColor, highlightColor, gradientColors, colorVariant, rtl, style, accessibilityLabel, accessible, testID.
Animations
<Skeleton.Rect animation="shimmer" />
<Skeleton.Rect animation="pulse" />
<Skeleton.Rect animation="wave" />
<Skeleton.Rect animation="breathing" />
<Skeleton.Rect animation="none" />When the OS "Reduce Motion" setting is on, any non-"none" animation automatically downgrades to a slow, low-amplitude breathing effect. Override via SkeletonProvider reducedMotion={false} to force animations regardless of the OS setting (use sparingly).
Stagger groups
<Skeleton.Group staggerDelay={80}>
<Skeleton.Rect width="100%" height={16} />
<Skeleton.Rect width="80%" height={16} />
<Skeleton.Rect width="60%" height={16} />
</Skeleton.Group>Each child's delay is automatically staggered unless it already specifies its own.
Presets
<Skeleton.Profile avatarSize={56} lines={2} />
<Skeleton.Card imageHeight={160} lines={3} showAvatar />
<Skeleton.Chat messages={5} />
<Skeleton.Product count={6} columns={2} />
<Skeleton.Video aspectRatio={16 / 9} showTitle showMeta />Every preset accepts count (repeat the block N times), gap, animation, style, and testID, plus its own shape-specific props.
Layout cloning
For bespoke layouts, describe the shape once and let SkeletonClone render matching placeholders:
<Skeleton.Clone
layout={{
direction: "row",
gap: 12,
children: [
{ shape: "circle", width: 48, height: 48 },
{
direction: "column",
gap: 6,
children: [
{ width: 120, height: 14 },
{ width: 80, height: 12 },
],
},
],
}}
/>Brand colors and custom styling
You can define a custom color palette at the provider level and apply it with colorVariant="brand":
<SkeletonProvider
colors={{
brand: {
light: {
background: "#F3F4F6",
highlight: "#E5E7EB",
},
dark: {
background: "#1F2937",
highlight: "#374151",
},
},
}}
>
<Skeleton.Rect colorVariant="brand" width={220} height={24} />
</SkeletonProvider>You can also override colors for a single shape:
<Skeleton.Rect
width="100%"
height={120}
borderRadius={12}
backgroundColor="#E5E7EB"
highlightColor="#F3F4F6"
/>Performance modes
<SkeletonProvider performanceMode="battery-saver">
<App />
</SkeletonProvider>battery-saver lengthens animation durations to reduce frame work; high and balanced keep full fidelity.
API reference
| Export | Description |
| --- | --- |
| Skeleton | Base component + namespace (Skeleton.Rect, .Circle, .Square, .Pill, .Group, .Clone, .Profile, .Card, .Chat, .Product, .Video) |
| SkeletonProvider | Global config provider (theme, animation, duration, performance mode, rtl, reducedMotion, colors) |
| useSkeletonTheme(colorVariant?) | Hook returning resolved { isDark, background, highlight } |
| useReducedMotion() | Hook returning the current OS reduce-motion boolean |
See src/types/index.ts for the full prop type definitions.
Contribution
Feel free to contribute, report issues, or suggest improvements.
Author
Neeraj Singh
License
MIT
