w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.46k stars 657 forks source link

[css-view-transitions-2] Property on `ViewTransition` that notifies when the transition has begun #9314

Open atscott opened 1 year ago

atscott commented 1 year ago

The existing promises on the ViewTransition interface (ready, finished, updateCallbackDone) all resolve at some time after the callback passed to startViewTransition executes. It would be useful to have a Promise that resolves right before the callback executes.

The Svelte blog shows an example of where this would be useful: https://svelte.dev/blog/view-transitions#getting-started-with-view-transitions.

  return new Promise((resolve) => {
        document.startViewTransition(async () => {
            resolve();
            await navigation.complete;
        });
    });

In order to use view transitions with the router, the navigation has to pause and wait for the browser to begin processing the view transition callback. Then the navigation resumes, which includes the DOM update. Finally, the router indicates back to the browser that the navigation (and DOM update) completed by resolving the navigation.complete Promise. This back-and-forth communication with the Promise at the start of the transition might be a common use-case for developers and frameworks to avoid a large chunk of code inside a closure for the startViewTransition callback.

If this property existed, the above code might instead look like this:

const transition = document.startViewTransition(navigation.complete);
return transition.beforeUpdateCallback; // or some other name for a promise that resolves right before the update callback happens
noamr commented 1 year ago

This seems pretty easy to add but also pretty easy to write in userland (albeit broilerplate-ish).

noamr commented 1 year ago

@jakearchibald any idea if this was discussed in the past? Seems like a reasonable proposal but perhaps there's historical context I'm missing.

jakearchibald commented 1 year ago

My main worry is that it would encourage folks to put the DOM change code outside the callback, meaning errors aren't captured.

atscott commented 1 year ago

How different would this be from the updateCallbackDone, just on the other side of things? i.e., it seems like that could have also been done in user-land by resolving a promise at the end of the callback and updateCallbackDone also has the same potential for updating DOM outside the callback.

jakearchibald commented 1 year ago

If you do your DOM updates after updateCallbackDone, I think it's pretty clear from the naming that you're not using the API correctly, and will run into issues.

noamr commented 1 year ago

When I look at the Svelte example, seems like they need it because of their API shape - the update of the DOM happens between resolving onNavigate and resolving navigation.complete.

So in their case it would look like onNavigate(() => document.startViewTransition(() => navigation.complete).beforeDOMUpdate);

This means that to make this work correctly, also navigation.complete has to reject if there was an error during navigation (to keep the behavior of skipping the transition if the update fails). I'm not sure if this API shape makes this clear.

So this dual-promise technique would work for Svelte (and perhaps for Angular in your case), but perhaps if we wanted to make it clear in the API it needs to mandate a dual promise, rather than pass one promise to the callback and one via willCallUpdateCallback? Not sure we'll come up with something that feels less broiler-platey than what we have.