Skip to content

feat(react-motion): add replayKey prop to replay motion without remounting#36108

Open
robertpenner wants to merge 10 commits into
microsoft:masterfrom
robertpenner:feat/motion-component-replay-key
Open

feat(react-motion): add replayKey prop to replay motion without remounting#36108
robertpenner wants to merge 10 commits into
microsoft:masterfrom
robertpenner:feat/motion-component-replay-key

Conversation

@robertpenner
Copy link
Copy Markdown
Collaborator

@robertpenner robertpenner commented May 6, 2026

  • Add an optional replayKey prop to MotionComponentProps.
  • When the value changes, the animation effect re-runs — cancelling any in-progress animation and replaying from the start on the same DOM element, without remounting the component or its children.
  • Includes tests verifying replay behaviour, DOM continuity, callbacks firing on replay (onMotionStart/onMotionFinish), and skip-motion fast-forward on replay.
  • Adds a Storybook story with a side-by-side before/after demo.
image

Previous Behavior

To retrigger a motion animation on an already-mounted component, the only declarative option was to change the React key prop, which forces a full unmount and remount of the subtree. This destroys the DOM nodes, resets child component state, and loses focus — even when all you want is to replay the animation.

New Behavior

MotionComponent accepts an optional replayKey prop (string | number). When the value changes, the animation replays from the beginning on the existing DOM element — cancelling any in-progress animation — without unmounting or remounting the component or its children. DOM continuity, focus, and child state are all preserved.

const [replayKey, setReplayKey] = React.useState(0);

<Fade.In replayKey={replayKey}>
  <div>Content</div>
</Fade.In>
<button onClick={() => setReplayKey(k => k + 1)}>Replay</button>

Future Work

@robertpenner robertpenner self-assigned this May 6, 2026
@robertpenner robertpenner force-pushed the feat/motion-component-replay-key branch from dd35075 to 0967549 Compare May 6, 2026 05:57
@robertpenner robertpenner force-pushed the feat/motion-component-replay-key branch from 0967549 to 864d814 Compare May 7, 2026 14:35
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

📊 Bundle size report

Package & Exports Baseline (minified/GZIP) PR Change
react-accordion
Accordion (including children components)
92.107 kB
29.097 kB
92.263 kB
29.152 kB
156 B
55 B
react-charts
AreaChart
402.548 kB
125.863 kB
402.705 kB
125.924 kB
157 B
61 B
react-charts
DeclarativeChart
753.304 kB
220.052 kB
753.461 kB
220.1 kB
157 B
48 B
react-charts
DonutChart
312.961 kB
96.495 kB
313.118 kB
96.551 kB
157 B
56 B
react-charts
FunnelChart
304.508 kB
93.326 kB
304.665 kB
93.387 kB
157 B
61 B
react-charts
GanttChart
385.649 kB
120.152 kB
385.805 kB
120.192 kB
156 B
40 B
react-charts
GaugeChart
312.394 kB
95.948 kB
312.551 kB
96.005 kB
157 B
57 B
react-charts
GroupedVerticalBarChart
393.525 kB
122.894 kB
393.682 kB
122.935 kB
157 B
41 B
react-charts
HeatMapChart
387.728 kB
121.263 kB
387.885 kB
121.32 kB
157 B
57 B
react-charts
HorizontalBarChart
292.691 kB
89.04 kB
292.848 kB
89.089 kB
157 B
49 B
react-charts
Legends
232.228 kB
69.849 kB
232.384 kB
69.894 kB
156 B
45 B
react-charts
LineChart
413.882 kB
128.765 kB
414.039 kB
128.807 kB
157 B
42 B
react-charts
PolarChart
341.357 kB
106.417 kB
341.514 kB
106.461 kB
157 B
44 B
react-charts
SankeyChart
209.97 kB
67.042 kB
210.127 kB
67.099 kB
157 B
57 B
react-charts
ScatterChart
393.264 kB
122.86 kB
393.421 kB
122.904 kB
157 B
44 B
react-charts
VerticalBarChart
430.006 kB
127.714 kB
430.163 kB
127.775 kB
157 B
61 B
react-charts
VerticalStackedBarChart
399.53 kB
124.283 kB
399.687 kB
124.326 kB
157 B
43 B
react-components
react-components: Accordion, Button, FluentProvider, Image, Menu, Popover
226.994 kB
68.166 kB
227.15 kB
68.229 kB
156 B
63 B
react-components
react-components: entire library
1.292 MB
324.681 kB
1.292 MB
324.736 kB
157 B
55 B
react-dialog
Dialog (including children components)
91.172 kB
28.31 kB
91.329 kB
28.371 kB
157 B
61 B
react-menu
Menu (including children components)
160.425 kB
50.891 kB
160.581 kB
50.94 kB
156 B
49 B
react-menu
Menu (including selectable components)
163.603 kB
51.535 kB
163.759 kB
51.585 kB
156 B
50 B
react-motion
@fluentui/react-motion - createMotionComponent()
4.156 kB
1.818 kB
4.312 kB
1.876 kB
156 B
58 B
react-motion
@fluentui/react-motion - createPresenceComponent()
5.908 kB
2.442 kB
6.064 kB
2.494 kB
156 B
52 B
react-popover
Popover
123.802 kB
39.735 kB
123.958 kB
39.789 kB
156 B
54 B
react-progress
ProgressBar
20.23 kB
7.866 kB
20.386 kB
7.925 kB
156 B
59 B
react-teaching-popover
TeachingPopover
102.196 kB
32.335 kB
102.352 kB
32.384 kB
156 B
49 B
react-toast
Toast (including Toaster)
92.099 kB
28.662 kB
92.256 kB
28.712 kB
157 B
50 B
react-tree
FlatTree
136.789 kB
40.787 kB
136.945 kB
40.84 kB
156 B
53 B
react-tree
PersonaFlatTree
138.617 kB
41.303 kB
138.773 kB
41.354 kB
156 B
51 B
react-tree
PersonaTree
134.677 kB
40.086 kB
134.833 kB
40.137 kB
156 B
51 B
react-tree
Tree
132.855 kB
39.62 kB
133.011 kB
39.673 kB
156 B
53 B
Unchanged fixtures
Package & Exports Size (minified/GZIP)
react-avatar
Avatar
48.492 kB
15.379 kB
react-avatar
AvatarGroup
17.468 kB
6.999 kB
react-avatar
AvatarGroupItem
61.513 kB
19.251 kB
react-breadcrumb
@fluentui/react-breadcrumb - package
103.889 kB
29.167 kB
react-charts
HorizontalBarChartWithAxis
63 B
83 B
react-charts
Sparkline
80.503 kB
26.644 kB
react-components
react-components: Button, FluentProvider & webLightTheme
67.61 kB
19.536 kB
react-components
react-components: FluentProvider & webLightTheme
40.806 kB
13.616 kB
react-datepicker-compat
DatePicker Compat
214.121 kB
62.046 kB
react-headless-components-preview
react-headless-components-preview: entire library
107.577 kB
31.646 kB
react-message-bar
MessageBar (all components)
23.418 kB
8.651 kB
react-motion
@fluentui/react-motion - PresenceGroup
1.727 kB
823 B
react-overflow
hooks only
11.966 kB
4.565 kB
react-persona
Persona
55.447 kB
17.311 kB
react-portal-compat
PortalCompatProvider
5.567 kB
2.237 kB
react-table
DataGrid
148.07 kB
44.013 kB
react-table
Table (Primitives only)
38.209 kB
12.782 kB
react-table
Table as DataGrid
119.815 kB
33.806 kB
react-table
Table (Selection only)
66.603 kB
19.023 kB
react-table
Table (Sort only)
65.246 kB
18.638 kB
react-tag-picker
@fluentui/react-tag-picker - package
174.546 kB
54.381 kB
react-tags
InteractionTag
13.742 kB
5.473 kB
react-tags
Tag
29.666 kB
9.433 kB
react-tags
TagGroup
71.009 kB
21.901 kB
react-timepicker-compat
TimePicker
105.613 kB
35.351 kB
🤖 This report was generated against f5bccb884ab92356ee9912cd29937d35e1d66d91

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

Pull request demo site: URL

@robertpenner robertpenner marked this pull request as ready for review May 7, 2026 15:32
@robertpenner robertpenner requested review from a team as code owners May 7, 2026 15:32
@robertpenner robertpenner requested a review from layershifter May 7, 2026 15:32
@robertpenner robertpenner force-pushed the feat/motion-component-replay-key branch from 68ec731 to bc88d21 Compare May 8, 2026 15:23
…nting

Add an optional replayKey prop to MotionComponentProps. When the value
changes, the animation effect re-runs — cancelling any in-progress
animation and replaying from the start on the same DOM element, without
remounting the component or its children. Includes tests verifying both
replay behaviour and DOM continuity.
@robertpenner robertpenner force-pushed the feat/motion-component-replay-key branch from bc88d21 to 35c8ed7 Compare May 11, 2026 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant