0
# Motion Component
1
2
The Motion component provides single element animations using spring physics. It's the simplest and most commonly used component in React Motion, ideal for basic state transitions, hover effects, and straightforward UI animations.
3
4
## Capabilities
5
6
### Motion Component
7
8
Creates a single animated element that transitions between style states using spring physics.
9
10
```javascript { .api }
11
/**
12
* Single element animation component using spring physics
13
* Animates from defaultStyle (or current style) to target style
14
*/
15
class Motion extends React.Component {
16
static propTypes = {
17
/** Initial style values (optional, defaults to target style values) */
18
defaultStyle: PropTypes.objectOf(PropTypes.number),
19
/** Target style with spring configurations (required) */
20
style: PropTypes.objectOf(PropTypes.oneOfType([
21
PropTypes.number,
22
PropTypes.object,
23
])).isRequired,
24
/** Render function receiving interpolated style values (required) */
25
children: PropTypes.func.isRequired,
26
/** Callback fired when animation completes (optional) */
27
onRest: PropTypes.func,
28
};
29
}
30
```
31
32
**Usage Examples:**
33
34
```javascript
35
import React, { useState } from 'react';
36
import { Motion, spring } from 'react-motion';
37
38
// Basic animation
39
function BasicMotion() {
40
const [open, setOpen] = useState(false);
41
42
return (
43
<Motion
44
defaultStyle={{width: 0, opacity: 0}}
45
style={{
46
width: spring(open ? 200 : 0),
47
opacity: spring(open ? 1 : 0)
48
}}
49
>
50
{({width, opacity}) => (
51
<div
52
style={{
53
width: `${width}px`,
54
opacity,
55
background: 'blue',
56
overflow: 'hidden'
57
}}
58
>
59
<button onClick={() => setOpen(!open)}>
60
Toggle
61
</button>
62
</div>
63
)}
64
</Motion>
65
);
66
}
67
68
// With custom spring config
69
function CustomSpringMotion() {
70
const [x, setX] = useState(0);
71
72
return (
73
<Motion
74
style={{
75
x: spring(x, {stiffness: 120, damping: 17})
76
}}
77
>
78
{({x}) => (
79
<div
80
style={{transform: `translateX(${x}px)`}}
81
onClick={() => setX(x === 0 ? 100 : 0)}
82
>
83
Click to move
84
</div>
85
)}
86
</Motion>
87
);
88
}
89
90
// With onRest callback
91
function MotionWithCallback() {
92
const [scale, setScale] = useState(1);
93
const [animating, setAnimating] = useState(false);
94
95
return (
96
<Motion
97
style={{scale: spring(scale)}}
98
onRest={() => {
99
setAnimating(false);
100
console.log('Animation completed!');
101
}}
102
>
103
{({scale}) => (
104
<div
105
style={{
106
transform: `scale(${scale})`,
107
transition: animating ? 'none' : undefined
108
}}
109
onClick={() => {
110
setAnimating(true);
111
setScale(scale === 1 ? 1.5 : 1);
112
}}
113
>
114
{animating ? 'Animating...' : 'Click to scale'}
115
</div>
116
)}
117
</Motion>
118
);
119
}
120
```
121
122
### defaultStyle Property
123
124
Optional initial style values. If not provided, the component will extract initial values from the target style.
125
126
```javascript { .api }
127
/**
128
* Initial style values for the animation
129
* If omitted, values are extracted from target style
130
*/
131
defaultStyle?: PlainStyle;
132
```
133
134
### style Property
135
136
Target style object containing numeric values or spring configurations. This is where you define what the animation should transition to.
137
138
```javascript { .api }
139
/**
140
* Target style with spring configurations
141
* Can mix plain numbers with spring() calls
142
*/
143
style: Style;
144
```
145
146
### children Property
147
148
Render function that receives the current interpolated style values and returns a React element.
149
150
```javascript { .api }
151
/**
152
* Render function receiving interpolated style values
153
* Called on every animation frame with current values
154
*/
155
children: (interpolatedStyle: PlainStyle) => ReactElement;
156
```
157
158
### onRest Property
159
160
Optional callback function fired when the animation reaches its target and stops moving.
161
162
```javascript { .api }
163
/**
164
* Callback fired when animation completes
165
* Useful for chaining animations or triggering side effects
166
*/
167
onRest?: () => void;
168
```
169
170
## Animation Behavior
171
172
### Spring Physics
173
174
The Motion component uses a spring-damper physics system:
175
- **No duration**: Animations run until they naturally settle
176
- **Interruption-safe**: Can be redirected mid-animation without jarring transitions
177
- **Natural feel**: Springs feel more organic than easing curves
178
179
### Performance
180
181
- Uses `requestAnimationFrame` for smooth 60fps animations
182
- Automatically stops when values reach target within precision threshold
183
- Handles browser tab switching gracefully by restarting timing
184
- Batches style updates through React's reconciliation
185
186
### State Management
187
188
Internally tracks:
189
- `currentStyle`: Current interpolated values
190
- `currentVelocity`: Current velocity for each animated property
191
- `lastIdealStyle`: Target values from previous frame
192
- `lastIdealVelocity`: Target velocity from previous frame
193
194
This state enables smooth interruptions when style prop changes during animation.
195
196
## Common Patterns
197
198
### Conditional Animations
199
200
```javascript
201
<Motion
202
style={{
203
x: spring(condition ? 100 : 0),
204
opacity: spring(visible ? 1 : 0)
205
}}
206
>
207
{({x, opacity}) => (
208
<div style={{transform: `translateX(${x}px)`, opacity}}>
209
Content
210
</div>
211
)}
212
</Motion>
213
```
214
215
### Multiple Properties
216
217
```javascript
218
<Motion
219
style={{
220
width: spring(expanded ? 200 : 50),
221
height: spring(expanded ? 200 : 50),
222
rotate: spring(expanded ? 45 : 0),
223
borderRadius: spring(expanded ? 20 : 5)
224
}}
225
>
226
{({width, height, rotate, borderRadius}) => (
227
<div
228
style={{
229
width: `${width}px`,
230
height: `${height}px`,
231
transform: `rotate(${rotate}deg)`,
232
borderRadius: `${borderRadius}px`
233
}}
234
>
235
Morphing box
236
</div>
237
)}
238
</Motion>
239
```
240
241
### Chained Animations
242
243
```javascript
244
function ChainedAnimation() {
245
const [stage, setStage] = useState(0);
246
247
return (
248
<Motion
249
style={{
250
x: spring(stage === 0 ? 0 : stage === 1 ? 100 : 200),
251
y: spring(stage < 2 ? 0 : 100)
252
}}
253
onRest={() => {
254
if (stage < 2) {
255
setStage(stage + 1);
256
}
257
}}
258
>
259
{({x, y}) => (
260
<div style={{transform: `translate(${x}px, ${y}px)`}}>
261
Stage {stage}
262
</div>
263
)}
264
</Motion>
265
);
266
}
267
```