0
# Layout Animations
1
2
Automatic layout animations that handle position and size changes smoothly, including shared layout transitions and reorder animations.
3
4
## Capabilities
5
6
### Layout Animation
7
8
Automatic animation of layout changes when element position or size changes.
9
10
```typescript { .api }
11
interface LayoutProps {
12
/** Enable layout animations */
13
layout?: boolean | "position" | "size";
14
/** Unique ID for shared layout animations */
15
layoutId?: string;
16
/** Root element for layout calculations */
17
layoutRoot?: React.RefObject<Element>;
18
/** Dependency array for layout updates */
19
layoutDependency?: any;
20
/** Scroll behavior during layout */
21
layoutScroll?: boolean;
22
}
23
```
24
25
**Usage Examples:**
26
27
```typescript
28
import { motion, useState } from "motion/react";
29
30
function LayoutExample() {
31
const [isExpanded, setIsExpanded] = useState(false);
32
33
return (
34
<motion.div
35
layout
36
onClick={() => setIsExpanded(!isExpanded)}
37
style={{
38
width: isExpanded ? 300 : 150,
39
height: isExpanded ? 200 : 100,
40
background: "#6366f1",
41
borderRadius: 8,
42
cursor: "pointer"
43
}}
44
>
45
<motion.p layout>
46
Click to {isExpanded ? "collapse" : "expand"}
47
</motion.p>
48
</motion.div>
49
);
50
}
51
```
52
53
### Shared Layout Animations
54
55
Animations between components that share the same layoutId, creating seamless transitions.
56
57
```typescript { .api }
58
interface SharedLayoutProps {
59
/** Shared layout identifier */
60
layoutId: string;
61
/** Layout transition configuration */
62
layoutTransition?: Transition;
63
}
64
```
65
66
**Usage Examples:**
67
68
```typescript
69
import { motion, useState } from "motion/react";
70
71
function SharedLayoutExample() {
72
const [selectedId, setSelectedId] = useState<string | null>(null);
73
74
const items = [
75
{ id: "1", title: "Item 1" },
76
{ id: "2", title: "Item 2" },
77
{ id: "3", title: "Item 3" }
78
];
79
80
return (
81
<div>
82
{items.map(item => (
83
<motion.div
84
key={item.id}
85
layoutId={item.id}
86
onClick={() => setSelectedId(item.id)}
87
style={{
88
width: selectedId === item.id ? 300 : 150,
89
height: selectedId === item.id ? 200 : 100,
90
background: "#f59e0b",
91
margin: 10,
92
borderRadius: 8,
93
cursor: "pointer"
94
}}
95
>
96
<motion.h3 layoutId={`title-${item.id}`}>
97
{item.title}
98
</motion.h3>
99
</motion.div>
100
))}
101
</div>
102
);
103
}
104
```
105
106
### LayoutGroup
107
108
Component for grouping related layout animations and coordinating transitions.
109
110
```typescript { .api }
111
/**
112
* Group related layout animations
113
* @param props - Layout group configuration
114
* @returns JSX element providing layout group context
115
*/
116
function LayoutGroup(props: LayoutGroupProps): JSX.Element;
117
118
interface LayoutGroupProps {
119
/** Child components */
120
children: React.ReactNode;
121
/** Unique group identifier */
122
id?: string;
123
/** Inherit layout group from parent */
124
inherit?: boolean;
125
}
126
```
127
128
**Usage Examples:**
129
130
```typescript
131
import { motion, LayoutGroup } from "motion/react";
132
133
function LayoutGroupExample() {
134
const [activeTab, setActiveTab] = useState("tab1");
135
136
return (
137
<LayoutGroup>
138
<div style={{ display: "flex" }}>
139
{["tab1", "tab2", "tab3"].map(tab => (
140
<motion.button
141
key={tab}
142
layout
143
onClick={() => setActiveTab(tab)}
144
style={{
145
position: "relative",
146
padding: "10px 20px",
147
background: activeTab === tab ? "#6366f1" : "transparent",
148
color: activeTab === tab ? "white" : "black",
149
border: "1px solid #6366f1",
150
cursor: "pointer"
151
}}
152
>
153
{tab}
154
{activeTab === tab && (
155
<motion.div
156
layoutId="activeTab"
157
style={{
158
position: "absolute",
159
inset: 0,
160
background: "#6366f1",
161
borderRadius: 4,
162
zIndex: -1
163
}}
164
/>
165
)}
166
</motion.button>
167
))}
168
</div>
169
</LayoutGroup>
170
);
171
}
172
```
173
174
### Reorder Components
175
176
Components for creating drag-to-reorder lists with smooth animations.
177
178
```typescript { .api }
179
interface Reorder {
180
/** Reorder group component */
181
Group: React.ForwardRefExoticComponent<ReorderGroupProps>;
182
/** Reorder item component */
183
Item: React.ForwardRefExoticComponent<ReorderItemProps>;
184
}
185
186
interface ReorderGroupProps<T> {
187
/** Child reorder items */
188
children: React.ReactNode;
189
/** Current order of items */
190
values: T[];
191
/** Callback when order changes */
192
onReorder: (newOrder: T[]) => void;
193
/** HTML element type */
194
as?: keyof HTMLElementTagNameMap;
195
/** Reorder axis */
196
axis?: "x" | "y";
197
/** Layout measurements */
198
layoutScroll?: boolean;
199
}
200
201
interface ReorderItemProps<T> {
202
/** Child content */
203
children?: React.ReactNode;
204
/** Item value */
205
value: T;
206
/** HTML element type */
207
as?: keyof HTMLElementTagNameMap;
208
/** Drag transition */
209
dragTransition?: Transition;
210
/** Layout transition */
211
layoutTransition?: Transition;
212
}
213
```
214
215
**Usage Examples:**
216
217
```typescript
218
import { Reorder } from "motion/react";
219
import { useState } from "react";
220
221
function ReorderExample() {
222
const [items, setItems] = useState([
223
{ id: 1, text: "Item 1" },
224
{ id: 2, text: "Item 2" },
225
{ id: 3, text: "Item 3" },
226
{ id: 4, text: "Item 4" }
227
]);
228
229
return (
230
<Reorder.Group
231
axis="y"
232
values={items}
233
onReorder={setItems}
234
style={{ listStyle: "none", padding: 0 }}
235
>
236
{items.map(item => (
237
<Reorder.Item
238
key={item.id}
239
value={item}
240
style={{
241
padding: "10px 20px",
242
margin: "5px 0",
243
background: "#f3f4f6",
244
borderRadius: 8,
245
cursor: "grab"
246
}}
247
>
248
{item.text}
249
</Reorder.Item>
250
))}
251
</Reorder.Group>
252
);
253
}
254
```
255
256
### Layout Transitions
257
258
Configuration options for customizing layout animation transitions.
259
260
```typescript { .api }
261
interface LayoutTransition extends Transition {
262
/** Transition for layout changes */
263
layout?: Transition;
264
/** Transition for position changes */
265
layoutPosition?: Transition;
266
/** Transition for size changes */
267
layoutSize?: Transition;
268
/** Transition for border radius changes */
269
layoutBorderRadius?: Transition;
270
/** Transition for opacity changes during layout */
271
layoutOpacity?: Transition;
272
}
273
```
274
275
### Layout Event Handlers
276
277
Event handlers for layout animation lifecycle events.
278
279
```typescript { .api }
280
interface LayoutEventHandlers {
281
/** Called before layout animation starts */
282
onLayoutAnimationStart?: () => void;
283
/** Called when layout animation completes */
284
onLayoutAnimationComplete?: () => void;
285
/** Called when layout measurements change */
286
onLayoutMeasure?: (layout: Box) => void;
287
}
288
289
interface Box {
290
x: number;
291
y: number;
292
width: number;
293
height: number;
294
}
295
```
296
297
### Advanced Layout Features
298
299
Advanced layout animation features for complex scenarios.
300
301
```typescript { .api }
302
interface AdvancedLayoutProps {
303
/** Preserve aspect ratio during layout */
304
layoutPreserveAspectRatio?: boolean;
305
/** Layout calculation mode */
306
layoutCalculation?: "auto" | "manual";
307
/** Custom layout measurement function */
308
layoutMeasure?: (element: Element) => Box;
309
/** Ignore transform during layout */
310
layoutIgnoreTransform?: boolean;
311
/** Layout animation priority */
312
layoutPriority?: number;
313
}
314
```
315
316
### CrossFade Animation
317
318
Smooth transitions between different components or states.
319
320
```typescript { .api }
321
/**
322
* Create crossfade animation between components
323
* @param components - Components to crossfade between
324
* @param activeIndex - Index of currently active component
325
* @returns JSX element with crossfade animation
326
*/
327
function crossfade<T extends React.ComponentType<any>>(
328
components: T[],
329
activeIndex: number
330
): JSX.Element;
331
```
332
333
### Layout Debugging
334
335
Tools for debugging layout animations and understanding layout calculations.
336
337
```typescript { .api }
338
interface LayoutDebugProps {
339
/** Show layout bounding boxes */
340
layoutDebug?: boolean;
341
/** Highlight layout changes */
342
layoutHighlight?: boolean;
343
/** Log layout measurements */
344
layoutLog?: boolean;
345
}
346
```
347
348
**Usage Examples:**
349
350
```typescript
351
import { motion } from "motion/react";
352
353
function DebugLayout() {
354
return (
355
<motion.div
356
layout
357
layoutDebug // Shows bounding boxes
358
layoutLog // Logs measurements to console
359
onLayoutMeasure={(layout) => {
360
console.log("Layout measured:", layout);
361
}}
362
style={{
363
width: Math.random() * 200 + 100,
364
height: Math.random() * 200 + 100,
365
background: "#ef4444"
366
}}
367
>
368
Debug layout
369
</motion.div>
370
);
371
}
372
```
373
374
### Layout Performance
375
376
Performance optimization techniques for layout animations.
377
378
```typescript { .api }
379
interface LayoutPerformanceProps {
380
/** Use GPU for layout animations */
381
layoutGPU?: boolean;
382
/** Layout animation priority */
383
layoutPriority?: "high" | "normal" | "low";
384
/** Batch layout updates */
385
layoutBatch?: boolean;
386
/** Throttle layout calculations */
387
layoutThrottle?: number;
388
}
389
```