Skip to content

Commit 62ac946

Browse files
feat: implement animations
1 parent d6a8dc6 commit 62ac946

File tree

9 files changed

+324
-16
lines changed

9 files changed

+324
-16
lines changed

README.md

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,68 @@
1-
# react-native-css-animations
1+
# React Native CSS Animations
2+
3+
Ready-to-use CSS Animation presets for React Native Reanimated.
4+
5+
## Installation
6+
7+
```
8+
yarn add [react-native-reanimated@next](https://github.com/software-mansion/react-native-reanimated)
9+
yarn add react-native-css-animations
10+
```
11+
12+
## Usage
13+
14+
### Spin
15+
16+
```typescript
17+
import { spin } from 'react-native-css-animations';
18+
import Animated from 'react-native-reanimated';
19+
20+
function App() {
21+
return (
22+
<Animated.View style={[styles.box, spin]}/>
23+
)
24+
}
25+
```
26+
27+
### Ping
28+
29+
```typescript
30+
import { ping } from 'react-native-css-animations';
31+
import Animated from 'react-native-reanimated';
32+
33+
function App() {
34+
return (
35+
<Animated.View style={[styles.notification, ping]}/>
36+
)
37+
}
38+
```
39+
40+
### Pulse
41+
42+
```typescript
43+
import { pulse } from 'react-native-css-animations';
44+
import Animated from 'react-native-reanimated';
45+
46+
function App() {
47+
return (
48+
<Animated.View style={[styles.skeleton, pulse]}/>
49+
)
50+
}
51+
```
52+
53+
### Bounce
54+
55+
```typescript
56+
import { bounce } from 'react-native-css-animations';
57+
import Animated from 'react-native-reanimated';
58+
59+
function App() {
60+
return (
61+
<Animated.View style={[styles.arrow, bounce]}/>
62+
)
63+
}
64+
```
65+
66+
## Credits
67+
68+
- The examples and animations were adopted from [Tailwind CSS](https://tailwindcss.com/docs/animation).

example/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ios/
2+
android/

example/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
"main": "index.js",
55
"scripts": {
66
"start": "expo start",
7-
"android": "expo start --android",
8-
"ios": "expo start --ios",
7+
"android": "expo run:android",
8+
"ios": "expo run:ios",
99
"web": "expo start --web"
1010
},
1111
"dependencies": {
@@ -15,6 +15,7 @@
1515
"react": "18.3.1",
1616
"react-dom": "18.3.1",
1717
"react-native": "0.76.6",
18+
"react-native-reanimated": "../react-native-reanimated-4.0.0-beta.3.1.tgz",
1819
"react-native-web": "~0.19.13"
1920
},
2021
"devDependencies": {

example/src/App.tsx

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,119 @@
1+
import { SafeAreaView, StyleSheet, Text, View } from 'react-native';
2+
import Animated from 'react-native-reanimated';
3+
import Fontisto from '@expo/vector-icons/Fontisto';
4+
import Entypo from '@expo/vector-icons/Entypo';
5+
import EvilIcons from '@expo/vector-icons/EvilIcons';
6+
import { bounce, ping, pulse, spin } from 'react-native-css-animations';
7+
18
export default function App() {
2-
return null;
9+
return (
10+
<SafeAreaView style={styles.container}>
11+
<Text style={styles.label}>Spin</Text>
12+
<View style={styles.button}>
13+
{/* Spin animation ⬇️ */}
14+
<Animated.View style={spin}>
15+
<EvilIcons name="spinner-3" size={24} color="white" />
16+
</Animated.View>
17+
<Text style={styles.buttonText}>Loading...</Text>
18+
</View>
19+
20+
<Text style={styles.label}>Ping</Text>
21+
<View style={styles.recording}>
22+
<Fontisto name="camera" size={18} color="black" />
23+
<View style={styles.notification} />
24+
{/* Ping animation ⬇️ */}
25+
<Animated.View style={[styles.notification, ping]} />
26+
</View>
27+
28+
<Text style={styles.label}>Pulse</Text>
29+
<View style={styles.skeletonContainer}>
30+
<Animated.View style={[styles.skeletonAvatar, pulse]} />
31+
<Animated.View style={[styles.skeletonText, pulse]} />
32+
</View>
33+
34+
<Text style={styles.label}>Bounce</Text>
35+
<Animated.View style={[styles.arrow, bounce]}>
36+
<Entypo name="chevron-down" size={24} color="black" />
37+
</Animated.View>
38+
</SafeAreaView>
39+
);
340
}
41+
42+
const styles = StyleSheet.create({
43+
container: {
44+
flex: 1,
45+
alignItems: 'center',
46+
padding: 24,
47+
margin: 24,
48+
},
49+
label: {
50+
fontSize: 24,
51+
fontWeight: 'bold',
52+
marginBottom: 18,
53+
marginTop: 24,
54+
},
55+
box: {
56+
width: 100,
57+
height: 100,
58+
backgroundColor: 'red',
59+
alignItems: 'center',
60+
justifyContent: 'center',
61+
},
62+
button: {
63+
flexDirection: 'row',
64+
alignItems: 'center',
65+
padding: 16,
66+
backgroundColor: '#3b82f6',
67+
borderRadius: 8,
68+
gap: 8,
69+
},
70+
buttonText: {
71+
color: 'white',
72+
fontSize: 16,
73+
fontWeight: 'bold',
74+
},
75+
recording: {
76+
width: 48,
77+
height: 48,
78+
borderRadius: 24,
79+
borderWidth: 2,
80+
borderColor: '#e2e8f0',
81+
alignItems: 'center',
82+
justifyContent: 'center',
83+
},
84+
notification: {
85+
position: 'absolute',
86+
top: 0,
87+
right: 0,
88+
width: 10,
89+
height: 10,
90+
borderRadius: 10,
91+
backgroundColor: 'red',
92+
},
93+
skeletonContainer: {
94+
flexDirection: 'row',
95+
alignItems: 'center',
96+
},
97+
skeletonAvatar: {
98+
width: 48,
99+
height: 48,
100+
borderRadius: 24,
101+
backgroundColor: '#e2e8f0',
102+
marginRight: 12,
103+
},
104+
skeletonText: {
105+
height: 24,
106+
width: 150,
107+
borderRadius: 8,
108+
backgroundColor: '#e2e8f0',
109+
},
110+
arrow: {
111+
width: 50,
112+
height: 50,
113+
borderRadius: 25,
114+
borderWidth: 2,
115+
alignItems: 'center',
116+
justifyContent: 'center',
117+
borderColor: '#e2e8f0',
118+
},
119+
});

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
"react": "18.3.1",
8181
"react-native": "0.76.6",
8282
"react-native-builder-bob": "^0.35.2",
83+
"react-native-reanimated": "./react-native-reanimated-4.0.0-beta.3.1.tgz",
8384
"release-it": "^17.10.0",
8485
"typescript": "^5.2.2"
8586
},
@@ -88,7 +89,8 @@
8889
},
8990
"peerDependencies": {
9091
"react": "*",
91-
"react-native": "*"
92+
"react-native": "*",
93+
"react-native-reanimated": ">=4.0.0"
9294
},
9395
"workspaces": [
9496
"example"
859 KB
Binary file not shown.

src/__tests__/index.test.tsx

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/index.tsx

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,73 @@
1-
export function noop() {}
1+
// MIT License
2+
3+
// Copyright (c) Tailwind Labs, Inc.
4+
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// SOFTWARE.
22+
23+
import { cubicBezier } from 'react-native-reanimated';
24+
import type { CSSStyleDeclaration } from 'react-native-reanimated/lib/typescript/css/types';
25+
26+
export const spin: CSSStyleDeclaration = {
27+
animationName: {
28+
to: {
29+
transform: [{ rotate: '360deg' }],
30+
},
31+
},
32+
animationDuration: '1s',
33+
animationTimingFunction: 'linear',
34+
animationIterationCount: 'infinite',
35+
};
36+
37+
export const ping: CSSStyleDeclaration = {
38+
animationName: {
39+
'75%, 100%': {
40+
transform: [{ scale: 2 }],
41+
opacity: 0,
42+
},
43+
},
44+
animationDuration: '1s',
45+
animationTimingFunction: cubicBezier(0, 0, 0.2, 1),
46+
animationIterationCount: 'infinite',
47+
};
48+
49+
export const pulse: CSSStyleDeclaration = {
50+
animationName: {
51+
'50%': {
52+
opacity: 0.5,
53+
},
54+
},
55+
animationDuration: '2s',
56+
animationTimingFunction: cubicBezier(0.4, 0, 0.6, 1),
57+
animationIterationCount: 'infinite',
58+
};
59+
60+
export const bounce: CSSStyleDeclaration = {
61+
animationName: {
62+
'0%, 100%': {
63+
transform: [{ translateY: '-25%' }],
64+
animationTimingFunction: cubicBezier(0.8, 0, 1, 1),
65+
},
66+
'50%': {
67+
transform: [{ translateY: '0%' }],
68+
animationTimingFunction: cubicBezier(0, 0, 0.2, 1),
69+
},
70+
},
71+
animationDuration: '1s',
72+
animationIterationCount: 'infinite',
73+
};

0 commit comments

Comments
 (0)