Skip to content

Commit b23c0c2

Browse files
committed
Bunch of updates
1 parent 58d042f commit b23c0c2

File tree

1 file changed

+127
-51
lines changed

1 file changed

+127
-51
lines changed

src/content/reference/react/ViewTransition.md

Lines changed: 127 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,20 @@ This API is only available inside React Server Components.
4040

4141
### `<ViewTransiton>` {/*viewtransition*/}
4242

43-
Wrap elements in `<ViewTransition>` to animate them when they update inside a [Transition](/reference/react/useTransition). Inside a Transition, React uses [heuristics](#heuristics) to determine if a `class` for the View Transition should be added to an element, and adds them for you automatically. The elements are then updated inside [`document.startViewTransition`](https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition) to trigger the animations.
43+
Wrap elements in `<ViewTransition>` to animate them when they update inside a [Transition](/reference/react/useTransition). React uses [heuristics](#heuristics) to determine if a View Transition activates for an animation:
4444

45+
- `enter`: If a `ViewTransition` itself gets inserted in this Transition, then this will activate.
46+
- `exit`: If a `ViewTransition` itself gets deleted in this Transition, then this will activate.
47+
- `update`: If a `ViewTransition` has any DOM mutations inside it that React is doing (such as a prop changing) or if the `ViewTransition` boundary itself changes size or position due to an immediate sibling. If there are nested` ViewTransition` then the mutation applies to them and not the parent.
48+
- `share`: If a named `ViewTransition` is inside a deleted subtree and another named `ViewTransition` with the same name is part of an inserted subtree in the same Transition, they form a Shared Element Transition, and it animates from the deleted one to the inserted one.
49+
50+
By default, `<ViewTransition>` animates with a smooth cross-fade (the browser default view transition). You can customize the animation by providing a [View Transition Class](#view-transition-class) to the `<ViewTransition>` component. You can use a customize animations for each kind of trigger (see [Styling View Transitions](#styling-view-transitions)).
4551

4652
<DeepDive>
4753

4854
#### How does `<ViewTransition>` work? {/*how-does-viewtransition-work*/}
4955

50-
Under the hood, React applies view-transition-name to inline styles of the nearest DOM node nested inside the `<ViewTransition>` component. If there are multiple siblings DOM nodes like `<ViewTransition><div /><div /></ViewTransition>` then React adds a suffix to the name to make each unique but conceptually they're part of the same one. React doesn't apply these eagerly but only at the time that boundary should participate in an animation.
56+
Under the hood, React applies `view-transition-name` to inline styles of the nearest DOM node nested inside the `<ViewTransition>` component. If there are multiple siblings DOM nodes like `<ViewTransition><div /><div /></ViewTransition>` then React adds a suffix to the name to make each unique but conceptually they're part of the same one. React doesn't apply these eagerly but only at the time that boundary should participate in an animation.
5157

5258
React automatically calls `startViewTransition` itself behind the scenes so you should never do that yourself. In fact, if you have something else on the page running a ViewTransition React will interrupt it. So it's recommended that you use React itself to coordinate these. If you had other ways of trigger ViewTransitions in the past, we recommend that you migrate to the built-in way.
5359

@@ -73,19 +79,27 @@ After the finished Promise of the `startViewTransition` is resolved, React will
7379

7480
#### Props {/*props*/}
7581

76-
* **optional** `default`: A string or object. The [View Transition Class](#view-transition-class) to apply when no other matching trigger is found.
82+
By default, `<ViewTransition>` animates with a smooth cross-fade. You can customize the animation, or specify a shared element transition, with these props:
83+
7784
* **optional** `enter`: A string or object. The [View Transition Class](#view-transition-class) to apply when enter is activated.
7885
* **optional** `exit`: A string or object. The [View Transition Class](#view-transition-class) to apply when exit is activated.
7986
* **optional** `update`: A string or object. The [View Transition Class](#view-transition-class) to apply when an update is activated.
8087
* **optional** `share`: A string or object. The [View Transition Class](#view-transition-class) to apply when a shared element is activated.
81-
* **optional** `name`: A string or object. The name of the View Transition. If not provided, React will use a unique name for each View Transition.
88+
* **optional** `default`: A string or object. The [View Transition Class](#view-transition-class) used when no other matching activation prop is found.
89+
* **optional** `name`: A string or object. The name of the View Transition used for shared element transitions. If not provided, React will use a unique name for each View Transition to prevent unexpected animations.
90+
91+
#### Callback {/*events*/}
92+
93+
These callbacks allow you to adjust the animation imperatively using the [animate](https://developer.mozilla.org/en-US/docs/Web/API/Element/animate) APIs:
8294

83-
#### Events {/*events*/}
95+
* **optional** `onEnter`: A function. React calls `onEnter` after an "enter" animation.
96+
* **optional** `onExit`: A function. React calls `onExit` after an "exit" animation.
97+
* **optional** `onShare`: A function. React calls `onShare` after an "share" animation.
98+
* **optional** `onUpdate`: A function. React calls `onUpdate` after an "update" animation.
8499

85-
* **optional** `onEnter`: A function. React calls `onEnter` after the View Transition animates an enter transition.
86-
* **optional** `onExit`: A function. React calls `onExit` after the View Transition animates an exit transition.
87-
* **optional** `onShare`: A function. React calls `onShare` after the View Transition animates a shared element transition.
88-
* **optional** `onUpdate`: A function. React calls `onUpdate` after the View Transition animates an update transition.
100+
Each callback receives as arguments:
101+
- `element`: The DOM element that was animated.
102+
- `types`: The [transition types)(/todo) included in the animation.
89103

90104
### View Transition Class {/*view-transition-classes*/}
91105

@@ -95,36 +109,24 @@ The View Transition Class is the CSS class name(s) applied by React during the t
95109

96110
The value `'none'` can be used to prevent a View Transition from activating for a specific trigger.
97111

98-
#### Caveats {/*caveats*/}
99-
100-
- By default, `setState` updates immediately and does not activate `<ViewTransition>`, only updates wrapped in a [Transition](/reference/react/useTransition). You can also use [`<Suspense>`](/reference/react/Suspense) to opt-in to a Transition to [reveal content](/link-to-suspense-below).
101-
- `<ViewTransition>` creates an image that can be moved around, scaled and cross-faded. Unlike Layout Animations you may have seen in React Native or Motion, this means that not every individual Element inside of it animates its position. This can lead to better performance and a more continuous feeling, smooth, animation compared to animating every individual piece. However, it can also lose continuity in things that should be moving by themselves. So you might have to add more `<ViewTransition>` boundaries manually as a result.
102-
- Many users may prefer not having animations on the page. React doesn't automatically disable animations for this case. We recommend that using the `@media (prefers-reduced-motion)` media query to disable animations or tone them down based on user preference. In the future, CSS libraries may have this built-in to their presets.
103-
- Currently, `<ViewTransition>` only works in the DOM. We're working on adding support for React Native and other platforms.
104-
105-
### Heuristics {/*heuristics*/}
106-
107-
Unlike if you manually add [`view-transition-name`](https://developer.mozilla.org/en-US/docs/Web/CSS/view-transition-name) in the DOM, not all React `<ViewTransition>` boundaries will activate each time something animates. Instead, React will use a set of built-in heuristic to determine which needs to participate in the current animation.
112+
### Styling View Transitions {/*styling-view-transitions*/}
108113

109-
There are currently four types of triggers:
114+
<Note>
110115

111-
- `enter`: If a ViewTransition itself gets inserted in this Transition, then this will activate.
112-
- `exit`: If a ViewTransition itself gets deleted in this Transition, then this will activate.
113-
- `update`: If a ViewTransition has any DOM mutations inside it that React is doing (such as a prop changing) or if the ViewTransition boundary itself changes size or position due to an immediate sibling. If there are nested ViewTransition then the mutation applies to them and not the parent.
114-
- `share`: If a named ViewTransition is inside a deleted subtree and another named ViewTransition with the same name is part of an inserted subtree in the same Transition, they form a Shared Element Transition and it animates from the deleted one to the inserted one.
116+
In many early examples of View Transitions around the web you'll have seen using a [`view-transition-name`](https://developer.mozilla.org/en-US/docs/Web/CSS/view-transition-name) and then style it using `::view-transition-...(my-name)` selectors. We don't recommend that for styling. Instead, we normally recommend using a View Transition Class instead.
115117

116-
- You can use a different animation for each kind of trigger (see [Styling View Transitions](#styling-view-transitions)).
118+
</Note>
117119

118-
### Styling View Transitions {/*styling-view-transitions*/}
120+
To customize the animation for a `<ViewTransition>` you can provide a View Transition Class to one of the activation props. The View Transition Class is a CSS class name that React applies to the child elements when the ViewTransition activates.
119121

120-
In many early examples of View Transitions around the web you'll have seen using a [`view-transition-name`](https://developer.mozilla.org/en-US/docs/Web/CSS/view-transition-name) and then style it using `::view-transition-...(my-name)` selectors. We don't recommend that for styling. Instead, we normally recommend using a View Transition Class instead.
122+
For example, to customize an "enter" animation, provide a class name to the `enter` prop:
121123

122124

123-
```js [[1, 1, "default"], [2, 1, "my-class"]]
124-
<ViewTransition default="my-class">
125+
```js [[1, 1, "enter"], [2, 1, "slide-in"]]
126+
<ViewTransition enter="slide-in">
125127
```
126128

127-
When the ViewTransition activates, it will add the <CodeStep step={1}>default</CodeStep> class name <CodeStep step={2}>my-class</CodeStep>. Then you can refer to this class using [view transition pseudo selectors](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API#pseudo-elements) to build reusable animations:
129+
When the ViewTransition activates an <CodeStep step={1}>"enter"</CodeStep> animation, React will add the class name <CodeStep step={2}>slide-in</CodeStep>. Then you can refer to this class using [view transition pseudo selectors](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API#pseudo-elements) to build reusable animations:
128130

129131
```css
130132
::view-transition-group(.my-class) {
@@ -137,8 +139,14 @@ When the ViewTransition activates, it will add the <CodeStep step={1}>default</C
137139

138140
}
139141
```
142+
In the future, CSS libraries may add built-in animations using View Transition Classes to make this easier to use.
143+
144+
#### Caveats {/*caveats*/}
140145

141-
We're excited to see many more CSS libraries adding built-in animations using View Transition Classes to make this easier to use.
146+
- By default, `setState` updates immediately and does not activate `<ViewTransition>`, only updates wrapped in a [Transition](/reference/react/useTransition). You can also use [`<Suspense>`](/reference/react/Suspense) to opt-in to a Transition to [reveal content](/link-to-suspense-below).
147+
- `<ViewTransition>` creates an image that can be moved around, scaled and cross-faded. Unlike Layout Animations you may have seen in React Native or Motion, this means that not every individual Element inside of it animates its position. This can lead to better performance and a more continuous feeling, smooth, animation compared to animating every individual piece. However, it can also lose continuity in things that should be moving by themselves. So you might have to add more `<ViewTransition>` boundaries manually as a result.
148+
- Many users may prefer not having animations on the page. React doesn't automatically disable animations for this case. We recommend that using the `@media (prefers-reduced-motion)` media query to disable animations or tone them down based on user preference. In the future, CSS libraries may have this built-in to their presets.
149+
- Currently, `<ViewTransition>` only works in the DOM. We're working on adding support for React Native and other platforms.
142150

143151
---
144152

@@ -270,26 +278,6 @@ It's important to properly use keys to preserve identity when reordering lists.
270278

271279
---
272280

273-
### Opting-out of an animation {/*opting-out-of-an-animation*/}
274-
275-
Sometimes you're wrapping a large existing component, like a whole page, and you want to animate some updates to, such as changing the theme. However, you don't want it to opt-in all updates inside the whole page to cross-fade when they're updating. Especially if you're incrementally adding more animations.
276-
277-
You can use the class "none" to opt-out of an animation. By wrapping your children in a "none" you can disable animations for updates to them while the parent still triggers.
278-
279-
```js
280-
<ViewTransition>
281-
<div className={theme}>
282-
<ViewTransition update="none">
283-
{children}
284-
</ViewTransition>
285-
</div>
286-
</ViewTransition>
287-
```
288-
289-
This will only animate if the theme changes and not if only the children update. The children can still opt-in again with their own `<ViewTransition>` but at least it's manual again.
290-
291-
---
292-
293281
### Animating from Suspense content {/*animating-from-suspense-content*/}
294282

295283
Just like any Transition React waits for data and new CSS (`<link rel="stylesheet" precedence="...">`) before running the animation. In addition to this ViewTransitions also wait up to 500ms for new fonts to load before starting the animation to avoid them flickering in later. In the future we plan on also waiting for images.
@@ -324,6 +312,94 @@ In this scenario, these are two separate ViewTransition instances each with thei
324312
You can achieve different effects depending on where you choose to place the `<ViewTransition>` boundary.
325313

326314
---
315+
### Opting-out of an animation {/*opting-out-of-an-animation*/}
316+
317+
Sometimes you're wrapping a large existing component, like a whole page, and you want to animate some updates to, such as changing the theme. However, you don't want it to opt-in all updates inside the whole page to cross-fade when they're updating. Especially if you're incrementally adding more animations.
318+
319+
You can use the class "none" to opt-out of an animation. By wrapping your children in a "none" you can disable animations for updates to them while the parent still triggers.
320+
321+
```js
322+
<ViewTransition>
323+
<div className={theme}>
324+
<ViewTransition update="none">
325+
{children}
326+
</ViewTransition>
327+
</div>
328+
</ViewTransition>
329+
```
330+
331+
This will only animate if the theme changes and not if only the children update. The children can still opt-in again with their own `<ViewTransition>` but at least it's manual again.
332+
333+
---
334+
335+
### Customizing `default` animations {/*customizing-default-animations*/}
336+
337+
TODO
338+
339+
---
340+
341+
### Customizing `enter` animations {/*customizing-enter-animations*/}
342+
343+
TODO
344+
345+
---
346+
347+
### Customizing `exit` animations {/*customizing-exit-animations*/}
348+
349+
TODO
350+
351+
---
352+
353+
### Customizing `update` animations {/*customizing-update-animations*/}
354+
355+
TODO
356+
357+
---
358+
359+
### Customizing `shared` animations {/*customizing-shared-animations*/}
360+
361+
TODO
362+
363+
---
364+
365+
### Custom animations with types {/*customizing-animations-with-types*/}
366+
You can use the [`addTransitionType`](/TODO) API to add a class name to the child elements when a specific transition type is activated for a specifc activation trigger. This allows you to customize the animation for each type of transition.
367+
368+
For example, to customize the animation for all forward and backward navigations:
369+
370+
```js
371+
<ViewTransition default={{
372+
'navigation-back': 'slide-right',
373+
'navigation-forward': 'slide-left',
374+
}}>
375+
<div>...</div>
376+
</ViewTransition>
377+
378+
// in your router:
379+
startTransition(() => {
380+
addTransitionType('navigation-' + navigationType);
381+
});
382+
```
383+
384+
When the ViewTransition activates a "navigation-back" animation, React will add the class name "slide-right". When the ViewTransition activates a "navigation-forward" animation, React will add the class name "slide-left".
385+
386+
In the future, routers and other libraries may add support for standard view-transition types and styles.
387+
388+
### Building View Transition enabled routers {/*building-view-transition-enabled-routers*/}
389+
390+
React waits for any pending Navigation to finish to ensure that scroll restoration happens within the animation. If the Navigation is blocked on React, your router must unblock in `useLayoutEffect` since `useEffect` would lead to a deadlock.
391+
392+
If a `startTransition` is started from the legacy popstate event, such as during a "back"-navigation then it must finish synchronously to ensure scroll and form restoration works correctly. This is in conflict with running a View Transition animation. Therefore, React will skip animations from popstate. Therefore animations won't run for the back button. You can fix this by upgrading your router to use the Navigation API.
393+
394+
TODO: add the navigation-forward and navigation-back recommendation?
395+
396+
---
397+
398+
### Adjusting animations {/*adjusting-animations*/}
399+
400+
TODO: example of using the callbacks with:
401+
- viewTransition.old.animate
402+
- -viewTransition.new.animate
327403

328404
## Troubleshooting {/*troubleshooting*/}
329405

0 commit comments

Comments
 (0)