Skip to content

Commit

Permalink
View Transition Class Names based on event kind (facebook#32050)
Browse files Browse the repository at this point in the history
This adds five props to `<ViewTransition>` that adds a specific
`view-transition-class` when React wants to animate it based on the
heuristic that triggers.

```js
<ViewTransition
  enter="slide-from-left"
  exit="slide-to-right"
  layout="slide"
  update="none"
  share="cross-fade"
>
```

- `enter`: The <ViewTransition> or its parent Component is mounted and
there's no other <ViewTransition> with the same name being deleted.
- `exit`: The <ViewTransition> or its parent Component is unmounted and
there's no other <ViewTransition> with the same name being deleted.
- `layout`: There are no updates to the content inside this
<ViewTransition> boundary itself but the boundary has resized or moved
due to other changes to siblings.
- `share`: This <ViewTransition> is being mounted and another
<ViewTransition> instance with the same name is being unmounted
elsewhere.
- `update`: The content of <ViewTransition> has changed either due to
DOM mutations or because an inner child <ViewTransition> has resized.

The existing `className` is the baseline and the others are added to it
to combine.

This is convenient to distinguish things like `enter` / `exit` but that
can already be expressed as CSS. The other cases can't be expressed as
purely CSS.

`"none"` is a special value that deactivates the view transition name
under that condition.

The most important feature of this is that you can now limit View
Transitions to only tigger when a particular DOM node is affected, not
when just any child updates, by opt-ing out a subtree. This is safer
when added to shared parent.

```js
<ViewTransition>
  <div>
     <ViewTransition className="none">
       {children}
     </ViewTransition>
  </div>
</ViewTransition>
```

This can't be fully expressed using neither just CSS nor the imperative
refs API since we need some way to have already removed the
`view-transition-name` when this happens. When you think about the
implementation details it might seem a bit strange that you specify the
`class` to `none` to remove the `name` but it's really about picking
which animation should happen for that case default (`undefined`), a
specific one (class) or none (`"none"`).
  • Loading branch information
sebmarkbage authored Jan 13, 2025
1 parent 540efeb commit cabd8a0
Show file tree
Hide file tree
Showing 3 changed files with 272 additions and 102 deletions.
4 changes: 2 additions & 2 deletions fixtures/view-transition/src/components/Page.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default function Page({url, navigate}) {
}}>
{show ? 'A' : 'B'}
</button>
<ViewTransition>
<ViewTransition className="none">
<div>
{show ? (
<div>
Expand Down Expand Up @@ -92,7 +92,7 @@ export default function Page({url, navigate}) {
<div>!!</div>
</ViewTransition>
</Activity>
{show ? <Component /> : <p>&nbsp;</p>}
{show ? <Component /> : null}
</div>
</ViewTransition>
</div>
Expand Down
Loading

0 comments on commit cabd8a0

Please sign in to comment.