Skip to content

Support nested ViewTransition enter/exit animations based on transition types behind flag#36135

Open
jackpope wants to merge 4 commits intofacebook:mainfrom
jackpope:nested-exit-vt
Open

Support nested ViewTransition enter/exit animations based on transition types behind flag#36135
jackpope wants to merge 4 commits intofacebook:mainfrom
jackpope:nested-exit-vt

Conversation

@jackpope
Copy link
Contributor

Adds experimental support for firing enter and exit animations on nested <ViewTransition> components when they specify type-based (object map) transition configs.

This is gated behind the enableViewTransitionNested feature flag.

Addresses the use case of animating individual items in a list (e.g. staggered fade-out of feed posts) when a parent ViewTransition is the one being mounted/unmounted.

Today, exit/enter only fire on the top-level ViewTransition that was directly mounted or unmounted. This is a good default. Cascading exit animations to every nested ViewTransition would cause unintended animations on simple list updates. But for intentional cases like staggered list exits during navigation, there's no way to opt in.

This PR lets you opt in per-component by passing an object map:

  <ViewTransition exit={{ 'nav-forward': `slow-fade-${index}`, default: 'none' }}>
    <FeedItem />
  </ViewTransition>

When the parent ViewTransition exits, React walks into nested ViewTransitions and fires their exit/enter if a transition type matches. String-only configs (exit="fade") are ignored by the nested walk, preserving the current top-level-only behavior.

ViewTransitionStatic subtreeFlags are cleared in completeWork. To avoid a full traversal, I've added ViewTransitionStaticNested. Looking for feedback on that approach.

@meta-cla meta-cla bot added the CLA Signed label Mar 24, 2026
@react-sizebot
Copy link

react-sizebot commented Mar 24, 2026

Comparing: c0d218f...ed9e090

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB = 1.88 kB 1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 612.88 kB 612.82 kB = 108.30 kB 108.30 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB = 1.88 kB 1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 678.81 kB 678.75 kB = 119.26 kB 119.25 kB
facebook-www/ReactDOM-prod.classic.js +0.41% 698.20 kB 701.08 kB +0.31% 122.65 kB 123.03 kB
facebook-www/ReactDOM-prod.modern.js +0.42% 688.52 kB 691.39 kB +0.31% 121.03 kB 121.40 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
react-native/implementations/ReactFabric-prod.fb.js +0.68% 423.20 kB 426.06 kB +0.53% 73.14 kB 73.52 kB
facebook-www/ReactReconciler-prod.modern.js +0.60% 509.83 kB 512.89 kB +0.49% 80.97 kB 81.36 kB
facebook-www/ReactReconciler-prod.classic.js +0.59% 520.11 kB 523.17 kB +0.48% 82.61 kB 83.00 kB
react-native/implementations/ReactFabric-profiling.fb.js +0.58% 496.66 kB 499.52 kB +0.43% 83.81 kB 84.18 kB
facebook-www/ReactART-prod.modern.js +0.54% 384.40 kB 386.49 kB +0.52% 64.34 kB 64.67 kB
facebook-www/ReactART-prod.classic.js +0.53% 394.31 kB 396.39 kB +0.51% 65.98 kB 66.32 kB
facebook-react-native/react-dom/cjs/ReactDOMClient-prod.js +0.44% 648.18 kB 651.04 kB +0.35% 114.21 kB 114.62 kB
facebook-react-native/react-dom/cjs/ReactDOMProfiling-prod.js +0.44% 653.84 kB 656.70 kB +0.35% 115.35 kB 115.75 kB
facebook-www/ReactART-dev.modern.js +0.42% 772.28 kB 775.53 kB +0.36% 121.05 kB 121.48 kB
facebook-www/ReactDOM-prod.modern.js +0.42% 688.52 kB 691.39 kB +0.31% 121.03 kB 121.40 kB
facebook-www/ReactART-dev.classic.js +0.42% 781.80 kB 785.06 kB +0.36% 122.78 kB 123.22 kB
facebook-www/ReactDOM-prod.classic.js +0.41% 698.20 kB 701.08 kB +0.31% 122.65 kB 123.03 kB
facebook-www/ReactDOMTesting-prod.modern.js +0.41% 702.92 kB 705.79 kB +0.30% 124.64 kB 125.02 kB
facebook-www/ReactDOMTesting-prod.classic.js +0.40% 712.60 kB 715.48 kB +0.30% 126.26 kB 126.64 kB
facebook-react-native/react-dom/cjs/ReactDOMClient-profiling.js +0.40% 723.75 kB 726.62 kB +0.31% 124.90 kB 125.29 kB
react-native/implementations/ReactFabric-dev.fb.js +0.39% 816.91 kB 820.13 kB +0.39% 130.89 kB 131.40 kB
facebook-react-native/react-dom/cjs/ReactDOMProfiling-profiling.js +0.39% 729.85 kB 732.71 kB +0.31% 126.11 kB 126.49 kB
facebook-www/ReactDOM-profiling.modern.js +0.38% 766.74 kB 769.62 kB +0.29% 132.03 kB 132.41 kB
facebook-www/ReactDOM-profiling.classic.js +0.37% 774.89 kB 777.76 kB +0.31% 133.35 kB 133.76 kB
facebook-www/ReactReconciler-dev.modern.js +0.37% 880.21 kB 883.46 kB +0.28% 137.04 kB 137.41 kB
facebook-www/ReactReconciler-dev.classic.js +0.37% 889.49 kB 892.74 kB +0.27% 138.76 kB 139.14 kB
facebook-react-native/react-dom/cjs/ReactDOMClient-dev.js +0.26% 1,221.95 kB 1,225.17 kB +0.21% 203.72 kB 204.14 kB
facebook-react-native/react-dom/cjs/ReactDOMProfiling-dev.js +0.26% 1,238.44 kB 1,241.67 kB +0.20% 206.56 kB 206.97 kB
facebook-www/ReactDOM-dev.modern.js +0.25% 1,281.63 kB 1,284.88 kB +0.19% 212.49 kB 212.90 kB
facebook-www/ReactDOM-dev.classic.js +0.25% 1,290.84 kB 1,294.10 kB +0.19% 214.31 kB 214.73 kB
facebook-www/ReactDOMTesting-dev.modern.js +0.25% 1,298.16 kB 1,301.42 kB +0.20% 216.25 kB 216.67 kB
facebook-www/ReactDOMTesting-dev.classic.js +0.25% 1,307.38 kB 1,310.63 kB +0.19% 218.09 kB 218.50 kB

Generated by 🚫 dangerJS against ed9e090

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.

2 participants