https://github.com/numandev1/react-native-auto-shimmer
Auto generated shimmer loading for React Native / Expo
https://github.com/numandev1/react-native-auto-shimmer
expo react-native shimmer shimmer-android shimmer-animation shimmer-effect shimmer-loading
Last synced: 1 day ago
JSON representation
Auto generated shimmer loading for React Native / Expo
- Host: GitHub
- URL: https://github.com/numandev1/react-native-auto-shimmer
- Owner: numandev1
- License: mit
- Created: 2026-04-06T11:28:12.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-04-08T13:25:31.000Z (2 months ago)
- Last Synced: 2026-04-08T13:25:56.526Z (2 months ago)
- Topics: expo, react-native, shimmer, shimmer-android, shimmer-animation, shimmer-effect, shimmer-loading
- Language: TypeScript
- Homepage:
- Size: 3.81 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README

# React Native Auto Shimmer
### Stop hand-coding skeleton screens. Capture them from your real UI in one click.
[](https://www.npmjs.com/package/react-native-auto-shimmer)
[](https://www.npmjs.com/package/react-native-auto-shimmer)
[](LICENSE)
[](https://reactnative.dev)
[](https://expo.dev)
[](CONTRIBUTING.md)
**โญ If this saves you time, star the repo โ it takes 2 seconds and helps others find it.**
**Auto Pulse**

**Auto Shimmer**

**ShimmerOverlay**

**ShimmerPlaceholder**

Auto-captured from live UI
Auto-captured from live UI
Wrap any element
Fixed-size box
---
## The problem with skeleton screens today
Every React Native developer has been here:
```
๐คฆ "OK let me eyeball this card width... maybe 340px? Let me check on a different device..."
๐คฆ "The design changed again. Rebuild all the skeletons."
๐คฆ "Why does the skeleton not match the real layout on iPad?"
```
Building skeletons by hand is a time sink that should not exist. **react-native-auto-shimmer fixes this permanently.**
---
## How it works (30 seconds)

*The Skeleton Inspector DevTools panel โ click Capture, get pixel-perfect skeletons instantly*
1. **Wrap** your component with ``
2. **Open** Skeleton Inspector in React Native DevTools
3. **Click Capture** โ real skeleton geometry is measured from the live fiber tree
4. **Delete** any unwanted pieces with the trash icon
5. **Save** โ a TypeScript file lands in `src/skeletons/` with a ready-to-paste code snippet
6. **Done** โ skeletons that match your UI exactly, on every device size
No guessing. No hardcoding. No drift.
---
## Three ways to use it
| | **Auto Shimmer** โญ Primary | **ShimmerOverlay** | **ShimmerPlaceholder** |
|---|---|---|---|
| **What** | Skeleton from live UI, zero manual work | Shimmer sweep over any element | Fixed-size shimmer box |
| **Layout** | Measured from real component | Wraps whatever you give it | You set `width` / `height` |
| **Responsive** | โ
% widths, any screen | โ | โ Fixed px |
| **Setup** | One-time DevTools capture | Wrap & go | Drop in |
| **Use when** | Building loading screens | Shine/highlight effects | Simple one-off placeholders |
> **Start with Auto Shimmer.** Drop to the manual options only for quick one-offs or pure visual effects.
---
## Installation
```sh
npm install react-native-auto-shimmer
# or
yarn add react-native-auto-shimmer
```
> No native modules ยท No `pod install` ยท No Gradle changes ยท Works with Expo ยท React Native โฅ 0.68
---
# Auto Shimmer โญ
> The main event. Capture pixel-perfect skeleton layouts directly from your running UI โ no measurement, no guesswork.
## Before vs. After
```diff
- // ๐ฉ The old way
- const SkeletonCard = () => (
-
-
-
- // ... and redo all of this every time the design changes
- );
+ // โ
With react-native-auto-shimmer
+
+
+
```
## Setup
### 1 โ Install dev dependencies
```sh
yarn add -D @rozenite/metro react-native-auto-shimmer-rozenite-plugin
```
### 2 โ Configure Metro
```js
// metro.config.js
const { getDefaultConfig } = require('@expo/metro-config'); // or require('metro-config')
const { withRozenite } = require('@rozenite/metro');
const { withSkeletonInspector } = require('react-native-auto-shimmer-rozenite-plugin/metro');
let config = getDefaultConfig(__dirname);
config = withSkeletonInspector(config);
if (process.env.WITH_ROZENITE === 'true') {
config = withRozenite(config, { enabled: true });
}
module.exports = config;
```
### 3 โ Register the plugin
```tsx
// App.tsx or index.js
if (__DEV__) {
const { getRozeniteDevToolsClient } = require('@rozenite/plugin-bridge');
const setupPlugin = require('react-native-auto-shimmer-rozenite-plugin').default;
getRozeniteDevToolsClient('react-native-auto-shimmer')
.then((client) => setupPlugin(client))
.catch((e) => console.warn('[SkeletonInspector] Could not connect:', e?.message));
}
```
### 4 โ Wrap your component
```tsx
import { Skeleton, SkeletonCapture } from 'react-native-auto-shimmer';
export function ArticleScreen() {
const [loading, setLoading] = useState(true);
return (
{/* Place SkeletonCapture inside Skeleton so it measures visible content */}
);
}
```
### 5 โ Run the inspector
```sh
WITH_ROZENITE=true yarn start
```
Open your app โ **React Native DevTools** โ **Rozenite tab** โ **Skeleton Inspector**
### 6 โ Capture, review, save
1. Navigate to your screen (make sure `loading` is `false` โ real content must be visible)
2. Click **โฌก Capture** โ skeletons are measured from the live layout
3. Delete unwanted pieces with the trash icon
4. Click **โ Save .ts (Responsive)** โ file lands in `src/skeletons/`
5. Copy the ready-to-paste snippet from the panel

> **Save .ts vs Save .json**
> `.ts` stores `x`/`w` as percentages โ scales to every screen size. **Use this.**
> `.json` stores raw dp values โ fastest for a quick snapshot on a single device.
---
## Using your skeletons
### Import directly (recommended)
```tsx
import cardSkeletons from './skeletons/card.skeletons'; // .ts โ responsive
```
### Register once, use everywhere (optional)
```ts
// App.tsx
import { registerSkeletons } from 'react-native-auto-shimmer';
import cardSkeletons from './skeletons/card.skeletons';
import profileSkeletons from './skeletons/profile.skeletons';
registerSkeletons({ card: cardSkeletons, profile: profileSkeletons });
```
```tsx
// Any screen โ no import needed
```
### Global config
```ts
import { configureSkeleton } from 'react-native-auto-shimmer';
configureSkeleton({
animate: 'shimmer', // 'pulse' | 'shimmer' | 'solid'
color: 'rgba(0,0,0,0.06)',
darkColor: 'rgba(255,255,255,0.08)',
});
```
---
## API โ ``
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `loading` | `boolean` | **required** | Show skeleton (`true`) or real content (`false`) |
| `children` | `ReactNode` | **required** | Your component |
| `name` | `string` | โ | Registry key set via `registerSkeletons` |
| `initialSkeletons` | `SkeletonResult \| ResponsiveSkeletons` | โ | Direct skeleton data โ takes priority over `name` |
| `animate` | `'pulse' \| 'shimmer' \| 'solid' \| boolean` | `'pulse'` | Animation style |
| `color` | `string` | `'rgba(0,0,0,0.08)'` | Skeleton colour (light mode) |
| `darkColor` | `string` | `'rgba(255,255,255,0.06)'` | Skeleton colour (dark mode) |
| `style` | `ViewStyle` | โ | Wrapper style โ set `width`, `height`, `borderRadius` here |
| `fallback` | `ReactNode` | โ | Shown when `loading=true` but no skeletons exist yet |
## API โ `` *(dev only)*
No-op in production โ tree-shakes to a plain `` with zero overhead.
| Prop | Type | Description |
|------|------|-------------|
| `name` | `string` | Identifier shown in Skeleton Inspector |
| `children` | `ReactNode` | The component to measure |
| `style` | `ViewStyle` | Forwarded to the wrapper View |
---
## Animation styles
| Value | Behaviour |
|-------|-----------|
| `'pulse'` | Opacity 100% โ 45% loop โ runs on the **native UI thread** |
| `'shimmer'` | Bright highlight sweeps left-to-right across all pieces |
| `'solid'` | Static โ no animation (good for Reduce Motion) |
---
## Responsive skeletons & dark mode
**Multi-breakpoint:** Capture at each device width. The file stores one entry per breakpoint; `` picks the nearest match automatically.
**Dark mode:** `` reads `useColorScheme()` internally โ pass `color` and `darkColor` or set them once with `configureSkeleton`.
---
# Manual Options
> Quick placeholders without the capture workflow.
---
## ShimmerOverlay
Adds a shimmer sweep to **any** existing element โ real content, buttons, images, cards. Not a loading placeholder; a visual highlight effect.
```tsx
import { ShimmerOverlay } from 'react-native-auto-shimmer';
// Basic
// Premium button highlight
// Staggered list
{items.map((item, i) => (
))}
// Programmatic control
const shimmerRef = useRef(null);
shimmerRef.current?.start()} />
```
### Props
| Prop | Type | Default | Description |
|---|---|---|---|
| `active` | `boolean` | `true` | Whether the animation runs |
| `color` | `string` | `'rgba(255,255,255,0.8)'` | Shimmer band colour |
| `duration` | `number` | `1500` | One cycle in ms |
| `delay` | `number` | `400` | Pause between cycles |
| `initialDelay` | `number` | `0` | Delay before first cycle |
| `angle` | `number` | `20` | Band angle in degrees |
| `bandWidth` | `number` | `60` | Band width in px |
| `mode` | `'normal' \| 'expand' \| 'shrink'` | `'normal'` | Band size style |
| `direction` | `'left-to-right' \| 'right-to-left'` | `'left-to-right'` | Sweep direction |
| `iterations` | `number` | `-1` | Cycles (-1 = infinite) |
| `respectReduceMotion` | `boolean` | `true` | Pauses on system Reduce Motion |
| `pauseOnBackground` | `boolean` | `true` | Pauses when app backgrounds |
| `onAnimationComplete` | `() => void` | โ | Called when all iterations finish |
### Ref methods
```tsx
ref.current?.start(); // Start
ref.current?.stop(); // Stop
ref.current?.restart(); // Restart from beginning
ref.current?.isAnimating(); // โ boolean
```
---
## ShimmerPlaceholder
A fixed-size shimmer box you size in code. Drop-in for [`react-native-shimmer-placeholder`](https://github.com/tomzaku/react-native-shimmer-placeholder) with **zero dependencies** โ no LinearGradient needed.
### Migrate in 2 lines
```diff
- import LinearGradient from 'react-native-linear-gradient';
- import { createShimmerPlaceholder } from 'react-native-shimmer-placeholder';
- const ShimmerPlaceHolder = createShimmerPlaceholder(LinearGradient);
+ import { createShimmerPlaceholder } from 'react-native-auto-shimmer';
+ const ShimmerPlaceHolder = createShimmerPlaceholder();
```
### Usage
```tsx
import { ShimmerPlaceholder } from 'react-native-auto-shimmer';
// Text line
{title}
// Avatar circle
// Dark mode
{label}
```
### Full placeholder card
```tsx
function ArticleCardPlaceholder({ loaded }: { loaded: boolean }) {
return (
{title}
{excerpt}
{authorName}
);
}
```
### Props
| Prop | Type | Default | Description |
|---|---|---|---|
| `width` | `number` | `200` | Width in px |
| `height` | `number` | `15` | Height in px |
| `visible` | `boolean` | `false` | `true` = show children, `false` = show shimmer |
| `shimmerColors` | `[string, string, string]` | `['#ebebeb','#d0d0d0','#ebebeb']` | Gradient colours |
| `isReversed` | `boolean` | `false` | Sweep right-to-left |
| `duration` | `number` | `1000` | One sweep in ms |
| `delay` | `number` | `0` | Delay before each sweep |
| `borderRadius` | `number` | `0` | Border radius |
| `style` | `StyleProp` | โ | Outer container style |
| `contentStyle` | `StyleProp` | โ | Children wrapper style |
| `shimmerStyle` | `StyleProp` | โ | Shimmer box style |
---
## FAQ
Do I need to keep <SkeletonCapture> in production?
No โ but you can safely leave it. In production (`__DEV__ === false`) it renders as a transparent `` with no bridge calls whatsoever.
The panel shows "No components found".
Navigate to the screen that mounts your ``. Components register on mount and deregister on unmount โ the panel reflects what's currently on screen.
<Skeleton> shows blank space instead of a skeleton.
No skeleton data has been passed yet. Use `fallback` while you complete the capture:
```tsx
}>
```
My component renders at different widths. Which do I capture?
Capture at every meaningful width. Each capture adds a breakpoint to the same file and `` picks the closest one at runtime.
Can I edit the skeleton data by hand?
Yes. `x`/`w` are % of container width, `y`/`h` are dp, `r` is border-radius in dp or `"50%"` for circles. Or just delete unwanted pieces in the inspector before saving.
Does it work with Expo?
Yes. No native modules. The Rozenite plugin uses Metro's `enhanceMiddleware` API, which Expo supports out of the box.
Does it work with the New Architecture (Fabric)?
Yes. `SkeletonCapture` detects the renderer at runtime and uses the correct measurement path for both Fabric and the legacy renderer.
Does it work with React Navigation / Expo Router?
Yes. `` registers on mount and cleans up on unmount โ no conflicts with any navigation library.
---
## Contributing
Bug fixes, features, and docs improvements are all welcome.
- [Development workflow](CONTRIBUTING.md#development-workflow)
- [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)
## Support the project
If this library saves you time, a star on GitHub goes a long way โ it helps other developers discover it.
---
inspired by [boneyard](https://github.com/0xGF/boneyard)
## License
MIT ยฉ [Numan](https://github.com/numandev1)
