0
# List Animation
1
2
Specialized component for animating arrays of keyed elements with smooth add/remove/reorder transitions. CSSMotionList automatically handles element lifecycle, position changes, and provides advanced diffing algorithms for optimal performance.
3
4
## Capabilities
5
6
### CSSMotionList Component
7
8
Advanced list animation component that tracks keyed elements and applies appropriate enter/leave animations as the list changes.
9
10
```typescript { .api }
11
/**
12
* List animation component for arrays of keyed elements
13
* @param props - Configuration extending CSSMotionProps with list-specific options
14
* @returns React component that renders animated list
15
*/
16
export function CSSMotionList(props: CSSMotionListProps): React.ReactElement;
17
18
interface CSSMotionListProps
19
extends Omit<CSSMotionProps, 'onVisibleChanged' | 'children'>,
20
Omit<React.HTMLAttributes<any>, 'children'> {
21
/** Array of React keys or key objects for list items */
22
keys: (React.Key | { key: React.Key; [name: string]: any })[];
23
/** Wrapper component type - string, component, or false for no wrapper */
24
component?: string | React.ComponentType | false;
25
/** Called when individual item visibility changes */
26
onVisibleChanged?: (visible: boolean, info: { key: React.Key }) => void;
27
/** Called when all items have been removed from the list */
28
onAllRemoved?: () => void;
29
/** Render function for each list item */
30
children?: (
31
props: {
32
visible?: boolean;
33
className?: string;
34
style?: React.CSSProperties;
35
index?: number;
36
[key: string]: any;
37
},
38
ref: (node: any) => void,
39
) => React.ReactElement;
40
}
41
```
42
43
**Usage Examples:**
44
45
```typescript
46
import { CSSMotionList } from "rc-motion";
47
48
// Basic animated list
49
function AnimatedList() {
50
const [items, setItems] = useState(['a', 'b', 'c']);
51
52
return (
53
<CSSMotionList
54
keys={items}
55
motionName="list-item"
56
component="ul"
57
>
58
{({ key, style, className }) => (
59
<li key={key} style={style} className={className}>
60
Item {key}
61
</li>
62
)}
63
</CSSMotionList>
64
);
65
}
66
67
// Advanced list with callbacks
68
function TodoList() {
69
const [todos, setTodos] = useState([
70
{ id: 1, text: 'Buy milk', completed: false },
71
{ id: 2, text: 'Walk dog', completed: true },
72
]);
73
74
return (
75
<CSSMotionList
76
keys={todos.map(todo => ({ key: todo.id, ...todo }))}
77
motionName="todo"
78
component="div"
79
onVisibleChanged={(visible, { key }) => {
80
console.log(`Todo ${key} visibility: ${visible}`);
81
}}
82
onAllRemoved={() => {
83
console.log('All todos removed');
84
}}
85
>
86
{({ key, style, className, ...props }) => (
87
<div key={key} style={style} className={className}>
88
<input
89
type="checkbox"
90
checked={props.completed}
91
onChange={() => toggleTodo(props.id)}
92
/>
93
<span>{props.text}</span>
94
<button onClick={() => removeTodo(props.id)}>Delete</button>
95
</div>
96
)}
97
</CSSMotionList>
98
);
99
}
100
```
101
102
### Key Management
103
104
System for tracking and diffing list items to determine appropriate animations.
105
106
```typescript { .api }
107
/**
108
* Key object interface for list items with optional metadata
109
*/
110
interface KeyObject {
111
key: string | number;
112
status?: DiffStatus;
113
[property: string]: any;
114
}
115
116
/**
117
* Status types for list item changes
118
*/
119
type DiffStatus = 'add' | 'keep' | 'remove' | 'removed';
120
121
/**
122
* Convert key or key object to normalized KeyObject format
123
* @param key - React key or key object
124
* @returns Normalized key object
125
*/
126
function wrapKeyToObject(key: React.Key | KeyObject): KeyObject;
127
128
/**
129
* Parse array of keys to KeyObject array
130
* @param keys - Array of keys to parse
131
* @returns Array of normalized key objects
132
*/
133
function parseKeys(keys: any[]): KeyObject[];
134
135
/**
136
* Compare previous and current keys to determine changes
137
* @param prevKeys - Previous key objects
138
* @param currentKeys - Current key objects
139
* @returns Array of key objects with diff status
140
*/
141
function diffKeys(
142
prevKeys: KeyObject[],
143
currentKeys: KeyObject[],
144
): KeyObject[];
145
```
146
147
### List State Management
148
149
Internal state interface for tracking list changes and animations.
150
151
```typescript { .api }
152
interface CSSMotionListState {
153
keyEntities: KeyObject[];
154
}
155
156
/**
157
* Generate CSSMotionList component with custom CSSMotion
158
* @param transitionSupport - Browser transition support flag
159
* @param CSSMotion - Custom CSSMotion component
160
* @returns Configured CSSMotionList class component
161
*/
162
function genCSSMotionList(
163
transitionSupport: boolean,
164
CSSMotion?: React.ComponentType<CSSMotionProps>,
165
): React.ComponentClass<CSSMotionListProps>;
166
```
167
168
### Motion Properties Inheritance
169
170
CSSMotionList inherits most properties from CSSMotionProps, enabling consistent animation behavior across single elements and lists.
171
172
```typescript { .api }
173
// Inherited from CSSMotionProps
174
interface InheritedMotionProps {
175
motionName?: MotionName;
176
motionAppear?: boolean;
177
motionEnter?: boolean;
178
motionLeave?: boolean;
179
motionLeaveImmediately?: boolean;
180
motionDeadline?: number;
181
removeOnLeave?: boolean;
182
leavedClassName?: string;
183
184
// Event handlers apply to each list item
185
onAppearPrepare?: MotionPrepareEventHandler;
186
onEnterPrepare?: MotionPrepareEventHandler;
187
onLeavePrepare?: MotionPrepareEventHandler;
188
onAppearStart?: MotionEventHandler;
189
onEnterStart?: MotionEventHandler;
190
onLeaveStart?: MotionEventHandler;
191
onAppearActive?: MotionEventHandler;
192
onEnterActive?: MotionEventHandler;
193
onLeaveActive?: MotionEventHandler;
194
onAppearEnd?: MotionEndEventHandler;
195
onEnterEnd?: MotionEndEventHandler;
196
onLeaveEnd?: MotionEndEventHandler;
197
}
198
```
199
200
### Advanced List Scenarios
201
202
Complex use cases and patterns for list animations.
203
204
```typescript
205
// Staggered animations
206
function StaggeredList() {
207
return (
208
<CSSMotionList
209
keys={items}
210
motionName="stagger"
211
motionDeadline={1000}
212
onEnterStart={(element, event) => {
213
const index = Array.from(element.parentNode.children).indexOf(element);
214
return {
215
animationDelay: `${index * 100}ms`,
216
opacity: 0,
217
transform: 'translateY(-20px)'
218
};
219
}}
220
onEnterActive={(element) => ({
221
opacity: 1,
222
transform: 'translateY(0)'
223
})}
224
>
225
{({ key, style, className, index }) => (
226
<div key={key} style={style} className={className}>
227
Staggered item {index}
228
</div>
229
)}
230
</CSSMotionList>
231
);
232
}
233
234
// Custom wrapper component
235
function CustomList() {
236
return (
237
<CSSMotionList
238
keys={items}
239
motionName="custom"
240
component={({ children, ...props }) => (
241
<div {...props} className="custom-list-wrapper">
242
<h2>Animated Items</h2>
243
{children}
244
</div>
245
)}
246
>
247
{({ key, style, className }) => (
248
<div key={key} style={style} className={className}>
249
Custom wrapped item
250
</div>
251
)}
252
</CSSMotionList>
253
);
254
}
255
```