elm-pages icon indicating copy to clipboard operation
elm-pages copied to clipboard

Support for page transition animations

Open ffigiel opened this issue 2 years ago • 5 comments

There was some discussion on Slack about page transition animations.

The difficult part is intercepting the internal LinkClicked or UrlChanged Msg to trigger the fade-out transition, and delaying rendering the new page while the animation plays.

Quoting Dillon's comment from Slack:

So to do that in elm-pages, there would need to be a way to hook in to the on url change Msg and change the behavior there, similar to what an ejected Main.elm in elm-spa lets you do: https://github.com/ryannhg/elm-spa/blob/main/docs/src/Main.elm#L81 I'm definitely open to exposing some of those details in elm-pages. I think it will need to be abstracted a bit, but it's doable in a nice way.

I made a small project for exploring this feature. The fade-in transition works well, the fade-out transition is implemented but not triggered anywhere (see the todo comment src/Shared.elm).

ffigiel avatar Sep 02 '21 21:09 ffigiel

I just thought of a different approach - we could superimpose the new page on top of the previous one (with position: relative/absolute in css) and play both animations simultaneously.

For this solution, user needs to be able to:

  1. remember the previous route/pageModel
  2. access the previous page's view function to render its body

ffigiel avatar Sep 03 '21 13:09 ffigiel

Interesting. It would definitely be possible at the framework-level to retain the previous page's Model while transitioning, and given a Page Model, it's possible to render the view (this is what the generated code is doing to render a normal view so it's just the normal codepath).

So that part seems doable - then the question would be how to expose that to the user. Would it just be to give the user access to a previousView of type Maybe View in their Shared.view function? Would that allow the user to do that sort of transition?

Shared Element Transitions API

Have you seen the in-progress spec for the Shared Element Transitions API? https://developer.chrome.com/blog/shared-element-transitions-for-spas/

It's still in early stages, but it could be a provide a more robust and high-level way to handle page transition animations. For example, it can hold a certain element statically as it performs the page transition. I'm not sure if Elm's Virtual DOM would conflict with this or not. Just throwing this API out there since it could be an interesting direction to explore.

dillonkearns avatar Dec 20 '21 05:12 dillonkearns

It's not what you all are talking about exactly, but if anyone is looking to hack in page transitions today i have an example here https://myreassurance.com https://github.com/13r0ck/myreassurance-website

13r0ck avatar Jan 21 '22 20:01 13r0ck

Having access to the previousView would seem to work for me. Does one perhaps also need access to, e.g., a Time.Posix of when the last transition occured?

I was fine with fade-ins only and used the OnPageChange message in Shared.elm to reset a variable in the model holding the time since the last page load. But this does not seem to work when following a link from another web page. One advantage is that I'm not limited to CSS Keyframes. But I think @megapctr has the better solution.

pelagisk avatar Jan 22 '22 13:01 pelagisk

Hi, first of all, thank you @dillonkearns for developing elm-pages! 😁 I was looking for ways to do page transitions and I found this discussion.

So that part seems doable - then the question would be how to expose that to the user. Would it just be to give the user access to a previousView of type Maybe View in their Shared.view function? Would that allow the user to do that sort of transition?

I like this approach! Also, it would be nice to have access to information about the previous page, to tune the transition based on that.

For example, sliding the new view from right when opening a page, and then sliding it out when going back could require knowing where we come from in the page hierarchy.

I’m still learning about the framework API, but would it be feasible to have access to a previousRoute or previousPageUrl?

MattiaVerticchio avatar Jul 15 '22 09:07 MattiaVerticchio