-
Notifications
You must be signed in to change notification settings - Fork 0
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[✨] View Transition Hook #55
Comments
Related QwikDev/qwik#3664 and QwikDev/qwik#2078 |
I'm going to point the other two issues here since they all want more or less the same thing. The View Transitions API isn't supported by WebKit yet but according to the tracking issue they are ok with it. Manu made https://pics-qwik.pages.dev/ last year using the So, do we just recommend to use this API or do we implement async callbacks in navigation to allow doing things manually? |
I think the discussion should go beyond navigation.
|
@GrandSchtroumpf so for animations you need to know which old DOM elements will be transformed to which new elements right? And with the ViewTransition API that is done via CSS. Suppose we decide to only support the ViewTransition API, what is still missing in Qwik? One thing we could do is put QRL attribures on DOM elements that are awaited before/after performing some DOM manipulation. Using |
Since this issue gathers all View Transition problems, let's split it into two part When does rendering happensThe ViewTransition API expect a callback that would work like that :
This is an imperative API, while Qwik is reactive, so we don't know when DOM is updated Here is a an example that illustrate the problem const hidden = useSignal(true);
useVisibleTask$(({ track }) => {
track(() => hidden.value);
// Case 1: flaky since the DOM might not have been updated at this point
document.startViewTransition(() => waitForNextFrame());
// Case 2: slow because it waits for 200ms to start the transition
document.startViewTransition(() => waitFor200ms());
}) In React they suggest to use Solution 1 const hidden = useSignal(true);
useVisibleTask$(({ track }) => {
track(() => hidden.value);
document.startViewTransition(() => onNextRender());
}) Note: Here we might not want to startViewTransition when state initializes. Solution 2 useViewTransition(({ track }) => track(() => hidden.value)); The hook would:
Note: This solution might be better designed to allow dev to select in which case run or not the transition. Hook into the transition flowThe API has two faces: CSS & JS.
CSS :
JS:
Example in my initial comment Solution 1: const location = useLocation();
useViewtransition(({ track, before, ready, finished }) => {
track(() => location.url);
before(async () => {
// Do something before `startViewTransition` is called
});
ready(async () => {
// Hooked into the `transition.ready` promise callback
// run WAPI animation
});
finished(async () => {
// Hooked into the `transition.finished` promise callback
// cleanup style or classes needed for the transition
})
});
useViewTransition(({ track }) => track(() => hidden.value)); The benefit of this API is that we can listen on page transition or local state transition with different behaviors. Solution 2: const transition = useViewtransition(({ before, ready, finished }) => {
before(async () => {
// Do something before `startViewTransition` is called
});
ready(async () => {
// Hooked into the `transition.ready` promise callback
// run WAPI animation
});
finished(async () => {
// Hooked into the `transition.finished` promise callback
// cleanup style or classes needed for the transition
})
});
return <Link transition={transition} /> This could be used in any UI library which wants to leverage the View Transition API power inside Qwik : const TabGroup = component$(({ transition }) => {
const selected = useState(null);
const select = $((e, el) => {
console.log(transition.id);
transition.start(() => selected.value = el.ariaControls)
});
return (
<button role="tab" onClick$={select} aria-controls="tab-panel-1">...</button>
<div role="tabpanel" id="tab-panel-1">...</div
)
}) ConclusionWe can have something like that, and use it inside the const useViewtransition = (params) => {
const initialized = useSignal(false);
const id = useId();
const start = $(async (cb = (() => {})) => {
await params.before();
const viewTransition = await new Promise((res, rej) => {
const transition = document.startViewTransition(async () => {
await cb();
await nextRendering();
res(transition);
})
});
viewTransition.read.then(params.ready);
viewTransition.finished.then(params.finished)
});
useTask$(({ track }) => {
if (!params.track) return;
track(params.track);
if (!initialized.value) return initialized.value = true;
if (!isServer) start();
})
return { id, start }
} |
Note that we could have a QRL prop on DOM nodes that gets awaited before it gets changed by Qwik. Would that be enough? |
I'm not sure, like a The |
No I meant like onBeforeDomNodeWillChange |
We moved this issue to |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Is your feature request related to a problem?
I'm trying a animate a list of item on page navigation. For that I'm animating with Javascript, but there is no way to hook into the transition from the link.
Describe the solution you'd like
Ideally the
Link
element &useNavigation
would expose a callback for that :Describe alternatives you've considered
We cannot set the animation inside
style
because this is a pseudo element ofhtml
.As we cannot update the pseudo element with Javascript and we cannot use css variable like that
::view-transition-old(var(--name))
.We cannot set a
<style>
on each element because it'll be removed before the view transition is ready.The only solution is to add
<style>
insidehead
with all the::view-transition-old()
pseudo class and remove them:Note: I'm not using
::view-transition-old(*)
because I want to target specific elements (not all) and I want to add delay.Additional context
No response
The text was updated successfully, but these errors were encountered: