Shimmer Effect Component
A highly customizable shimmer effect component for React Native Expo with smooth spring animations. Perfect for creating premium UI effects like loading states, highlight animations, and paywall subscriptions.
Features
- ✨ Smooth spring-based animations
- 🎨 Fully customizable colors, angles, and timing
- 📏 Dynamic stripe configuration
- 🚀 Zero-delay first animation
- 💫 Gradient opacity support (center to edges)
Installation
import { ShimmerPressableView } from '@/components/shimmer-pressable-view';
import { ShimmerEffectStripe } from '@/components/shimmer-effect-stripe';Basic Usage
Simple Shimmer Button
import { ShimmerPressableView } from '@/components/shimmer-pressable-view';
<ShimmerPressableView
shimmer
onPress={() => console.log('Pressed')}
>
<Text>Click me</Text>
</ShimmerPressableView>With Custom Configuration
<ShimmerPressableView
shimmer
shimmerConfig={{
delay: 2000,
duration: 2000,
angle: 30,
color: 'rgba(255, 215, 0, 0.3)',
stripeCount: 5,
}}
backgroundColor="#155A3A"
borderRadius={16}
onPress={handlePress}
>
<Text>Premium Button</Text>
</ShimmerPressableView>API Reference
ShimmerPressableView Props
| Prop | Type | Default | Description |
|---|---|---|---|
shimmer | boolean | true | Enable shimmer effect |
withShimmer | boolean | - | Alias for shimmer (deprecated) |
shimmerConfig | ShimmerConfig | - | Shimmer configuration object |
pressScale | number | 0.95 | Scale value when pressed (0-1) |
pressDuration | number | 200 | Animation duration for press feedback (ms) |
containerStyle | ViewStyle | - | Custom container style |
contentStyle | ViewStyle | - | Custom content style |
backgroundColor | string | '#2C2C2E' | Background color |
width | number | - | Button width (optional, uses flex if not provided) |
height | number | - | Button height (optional, uses flex if not provided) |
borderRadius | number | 24 | Border radius |
onPressIn | () => void | - | Custom onPressIn handler |
onPressOut | () => void | - | Custom onPressOut handler |
children | React.ReactNode | - | Button content |
ShimmerConfig
| Property | Type | Default | Description |
|---|---|---|---|
delay | number | 2000 | Delay between shimmer cycles (ms) |
duration | number | 1100 | Base duration for shimmer animation (ms) |
angle | number | 30 | Rotation angle in degrees |
color | string | 'rgba(180, 180, 180, 0.2)' | Shimmer color |
stripes | ShimmerStripe[] | - | Custom stripe configuration array |
stripeCount | number | 3 | Number of stripes (only used if stripes is not provided) |
ShimmerStripe
| Property | Type | Description |
|---|---|---|
width | number | Width of the stripe |
opacity | number | Opacity of the stripe (0-1) |
Advanced Examples
Custom Stripe Configuration
Create a custom gradient effect with specific stripe widths and opacities:
<ShimmerPressableView
shimmer
shimmerConfig={{
color: 'rgba(255, 215, 0, 0.3)',
stripes: [
{ width: 30, opacity: 0.2 },
{ width: 25, opacity: 0.6 },
{ width: 20, opacity: 1.0 },
{ width: 25, opacity: 0.6 },
{ width: 30, opacity: 0.2 },
],
}}
>
<Text>Custom Gradient</Text>
</ShimmerPressableView>Multiple Stripe Count
Use more stripes for a smoother effect. Stripe opacity is calculated automatically based on the number of stripes:
- Stripe 1: ~0.3 opacity
- Stripe 2: ~0.65 opacity
- Stripe 3: 1.0 opacity
- Stripe 4: ~0.65 opacity
- Stripe 5: ~0.3 opacity
- Stripe 6: ~0.15 opacity
- Stripe 7: ~0.075 opacity
Try to use an odd number of stripes for a more natural effect.
<ShimmerPressableView
shimmer
shimmerConfig={{
stripeCount: 7,
color: 'rgba(255, 255, 255, 0.25)',
}}
>
<Text>Smooth Shimmer</Text>
</ShimmerPressableView>Paywall Integration
Perfect for highlighting premium subscription options:
<Pressable style={styles.subscriptionCard}>
<ShimmerPressableView
shimmer
shimmerConfig={{
delay: 2000,
duration: 2000,
angle: 30,
color: 'rgba(255, 215, 0, 0.3)',
stripeCount: 5,
}}
containerStyle={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
backgroundColor="transparent"
borderRadius={16}
pointerEvents="none"
/>
<View style={styles.cardContent}>
<Text>Annual Pass</Text>
<Text>$25</Text>
</View>
</Pressable>Default Stripe Pattern
When using stripeCount without custom stripes, the component automatically generates a gradient pattern:
- Center stripe: Highest opacity (1.0), wider width
- Edge stripes: Lower opacity (~0.3), narrower width
- Gradient: Smooth transition from center to edges
For example, with stripeCount: 5:
- Stripe 1 (left): ~0.3 opacity, 16px width
- Stripe 2: ~0.65 opacity, 20px width
- Stripe 3 (center): 1.0 opacity, 24px width
- Stripe 4: ~0.65 opacity, 20px width
- Stripe 5 (right): ~0.3 opacity, 16px width
Spring Animation Configuration
The shimmer uses spring physics for smooth, natural animations:
withSpring(targetValue, {
damping: 25, // Controls oscillation (higher = less bounce)
stiffness: 60, // Controls speed (higher = faster)
mass: 1.2, // Controls inertia (higher = slower)
})Adjust these values in the component code to fine-tune the animation feel.
Best Practices
- Color Selection: Use semi-transparent colors (e.g.,
rgba(255, 215, 0, 0.3)) for subtle effects - Stripe Count: Use 3-5 stripes for most cases, 7+ for very smooth gradients
- Delay Timing: 2000-3000ms delay works well for most UI contexts
- Angle: 30 degrees is optimal for most use cases
- Performance: The component is optimized to prevent unnecessary re-animations
Troubleshooting
Animation doesn't start
- Ensure
shimmerprop istrue - Check that container has a valid width (component measures layout automatically)
Animation restarts on re-render
- This is prevented automatically, but if issues persist, check that the component isn't being unmounted/remounted
Too fast/slow animation
- Adjust
damping,stiffness, andmassvalues in the spring configuration - Modify
delayfor timing between cycles
TypeScript Support
Full TypeScript support with exported interfaces:
import type {
ShimmerConfig,
ShimmerStripe
} from '@/components/shimmer-pressable-view';License
Part of the react native components library.