react-native-animated-glow
Version:
A performant, highly-customizable animated glow effect for React Native, powered by Skia and Reanimated.
226 lines (183 loc) • 9.41 kB
Markdown
# React Native Animated Glow v3.0.1
<div align="center">
[](https://www.npmjs.com/package/react-native-animated-glow)
[](https://github.com/realimposter/react-native-animated-glow/blob/main/LICENSE)
[](https://www.npmjs.com/package/react-native-animated-glow)
<br/>
<a href="https://github.com/realimposter/react-native-animated-glow">
<img src="https://img.shields.io/github/stars/realimposter/react-native-animated-glow?style=social" alt="GitHub stars">
</a>
</div>
A performant, highly-customizable animated glow effect component for React Native, powered by **Skia** and **Reanimated 3**.

## Live Demo & Builder
Check out the **[live web demo and interactive builder](https://reactnativeglow.com/)** to see the component in action, browse tutorials, and create your own presets.
## Features
- **GPU-Powered Performance:** Built with Skia for smooth, 60 FPS animations that run on the UI thread.
- **Intelligent State Blending:** Responds to `hover` and `press` events by smoothly interpolating between different glow configurations.
- **Highly Customizable:** Control colors, speed, shape, size, opacity, and more through a flexible `glowLayers` API.
- **Advanced Effects:**
- Create flowing **gradient glows and borders**.
- Render glows `behind`, `inside` (clipped), or `over` your component.
- Achieve "comet trail" effects with variable `glowSize` arrays.
- **Easy Web Setup:** Skia's CanvasKit WASM file is loaded automatically from a CDN, no extra configuration needed.
- **Presets Included:** Ships with professionally designed presets to get you started instantly.
## Installation
**1. Install the library:**
```bash
npm install react-native-animated-glow
```
**2. Install Peer Dependencies:**
The library depends on Skia, Reanimated, and Gesture Handler.
```bash
npm install @shopify/react-native-skia react-native-reanimated react-native-gesture-handler
```
**3. Configure Dependencies:**
You must follow the installation guides for the peer dependencies to ensure they are configured correctly for your project.
- [React Native Skia Docs](https://shopify.github.io/react-native-skia/docs/getting-started/installation)
- [Reanimated Docs](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#installation) (Remember to add the Babel plugin!)
- [Gesture Handler Docs](https://docs.swmansion.com/react-native-gesture-handler/docs/fundamentals/installation) (Remember to add `GestureHandlerRootView`!)
## Usage
The best way to use the component is with a `PresetConfig` object, which makes your styles reusable and type-safe.
```jsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import AnimatedGlow, { type PresetConfig } from 'react-native-animated-glow';
// 1. Define your preset
const myCoolPreset: PresetConfig = {
metadata: {
name: 'My Cool Preset',
textColor: '#FFFFFF',
category: 'Custom',
tags: ['interactive']
},
states: [
{
name: 'default', // The base style for the component
preset: {
cornerRadius: 50,
outlineWidth: 2,
borderColor: '#E0FFFF',
glowLayers: [
{ colors: ['#00BFFF', '#87CEEB'], opacity: 0.5, glowSize: 30 },
]
}
},
// 2. Define interactive states
{
name: 'hover',
transition: 300, // 300ms transition into this state
preset: {
glowLayers: [{ glowSize: 40 }] // On hover, make the glow bigger
}
},
{
name: 'press',
transition: 100, // A faster transition for press
preset: {
glowLayers: [{ glowSize: 45, opacity: 0.6 }]
}
}
]
};
// 3. Use it in your component
export default function MyGlowingComponent() {
return (
<AnimatedGlow preset={myCoolPreset}>
<View style={styles.box}>
<Text style={styles.text}>I'm Interactive!</Text>
</View>
</AnimatedGlow>
);
}
const styles = StyleSheet.create({
box: { paddingVertical: 20, paddingHorizontal: 40, backgroundColor: '#222' },
text: { color: 'white', fontWeight: 'bold' }
});
```
## Controlling States
The `AnimatedGlow` component is stateless by default and is controlled via the `activeState` prop. This gives you complete control to connect it to any gesture or state management system.
The recommended way to handle user interactions is to wrap your content in a `Pressable` and use `React.useState` and `React.useRef` to manage the component's state between `'default'`, `'hover'`, and `'press'`.
Here is a robust example demonstrating how to handle both press and hover events correctly:
```jsx
import React, { useState, useRef } from 'react';
import { View, Text, StyleSheet, Pressable } from 'react-native';
// Import the GlowEvent type for type safety
import AnimatedGlow, { glowPresets, type GlowEvent } from 'react-native-animated-glow';
export default function MyInteractiveButton() {
// 1. State for the active glow effect ('default', 'hover', 'press')
const [glowState, setGlowState] = useState<GlowEvent>('default');
// 2. Ref to track if the cursor is currently hovering over the element
const isHovered = useRef(false);
return (
<AnimatedGlow
preset={glowPresets.defaultRainbow}
// 3. Pass the state to the activeState prop to control the glow
activeState={glowState}
>
<Pressable
style={styles.button}
onPress={() => console.log('Button Pressed!')}
// --- Press Events ---
onPressIn={() => setGlowState('press')}
onPressOut={() => {
// When the press is released, transition to 'hover' if the cursor
// is still over the button, otherwise return to 'default'.
setGlowState(isHovered.current ? 'hover' : 'default');
}}
// --- Hover Events (for Web, macOS, Windows) ---
onHoverIn={() => {
isHovered.current = true;
// Only transition to hover state if not being actively pressed.
if (glowState !== 'press') {
setGlowState('hover');
}
}}
onHoverOut={() => {
isHovered.current = false;
// Only transition to default state if not being actively pressed.
if (glowState !== 'press') {
setGlowState('default');
}
}}
>
<Text style={styles.buttonText}>Tap or Hover Me</Text>
</Pressable>
</AnimatedGlow>
);
}
const styles = StyleSheet.create({
button: {
paddingVertical: 20,
paddingHorizontal: 40,
backgroundColor: '#222'
},
buttonText: {
color: 'white',
fontWeight: 'bold',
textAlign: 'center'
}
});
```
## API Reference
For a complete list of all available props and their descriptions, please see the **[Docs Tab](https://reactnativeglow.com/docs)** in the live demo app.
## Changelog
### `v3.0.1`
- Added `activeState` prop.
- Removed insternal state management
### `v3.0.0` (Breaking Changes)
This version introduces a more powerful and intelligent animation system along with a complete restructuring of the preset API for better organization and type safety.
- **New Feature: Intelligent Animation Blending:** A new animation system powered by Reanimated worklets smoothly interpolates *between* state configurations. When you hover, press, or return to default, every animatable property (colors, sizes, opacity, etc.) will transition gracefully over the specified duration.
- **New Feature: Reworked State Management API:** The `preset` prop now expects a `PresetConfig` object with a `states` array. All visual styles, including the `default` look, are defined within this array. This makes presets more organized and powerful.
- **Architectural Improvement:** All glow layers, placements (`behind`, `inside`, `over`), and the animated border are now rendered in a single, unified Skia shader for maximum efficiency.
- **BREAKING CHANGE:** The `preset` prop format has been completely overhauled. Old flat preset objects are incompatible and must be migrated to the new `PresetConfig` structure, which includes a `metadata` object and a `states` array.
- **BREAKING CHANGE:** The `randomness` prop has been removed from the core API.
### `v2.0.0`
This version marked a complete architectural rewrite for maximum performance and flexibility.
- **Complete Rewrite with Skia:** The library is now powered by **Skia** and **Reanimated 3**, running animations smoothly on the UI thread.
- **Interactive States:** Added support for `hover` and `press` events with configurable transitions using `react-native-gesture-handler`.
- **BREAKING CHANGE:** The library now requires `@shopify/react-native-skia`, `react-native-reanimated`, and `react-native-gesture-handler` as peer dependencies. The old props (`glowColor`, `glowSize`, etc.) have been replaced by the `glowLayers` API.
### `v1.0.0`
- Initial release using glow particles and reanimated
## License
This project is licensed under the MIT License.