/elm-view-transitions

A proof of concept of the View Transitions API in Elm.

Primary LanguageElmMIT LicenseMIT

View Transitions API in Elm

Screenshot.-.10.March.2023.mp4

Background

View Transitions API docs

This example is the most relevant demo:

This repo uses the single-page app wiring described in https://github.com/elm/browser/blob/1.0.2/notes/navigation-in-elements.md.

Architecture

Transition state

I defined a Transition type:

type Transition
   = To Route
   | From Route

Essentially what is happening here is we are capturing a "snapshot" of a "Transition To state" and a "Transition From state".

That is, once we know which Route we are transitioning to, we can set that transition. This lets the user set any related CSS to tell the View Transitions API which elements are which on each page relative to that specific to/from transition.

For example, in this app I have type Route = Index | Detail String.

Let's say we being on Index. Our initial Model is:

{ route = Index
, transition = Just (To Index)
}

Once a link to a detail page is clicked, pushUrl is called and we call the JS app.ports.onTransitionStart.send(url); which triggers the TransitionStart Msg.

That gives us a Model:

{ route = Index
, transition = Just (To (Detail "1"))
}

Just for enough time for the view to render with a class "title-element", which has view-transition-name: title-element; on the first item on the Index page. This is the first snapshot ("Transition To state").

Finally, we call the magic function, document.startViewTransition. Within the callback function to startViewTransition, we do

history.pushState({}, "", url);
app.ports.onUrlChange.send(location.href);

This changes the browser's URL, and onUrlChange triggers the Msg UrlChanged.

Now our Model becomes:

{ route = Detail "1"
, transition = Just (From Index)
}

This is our "Transition From State".

In this particular example, we don't need the context that we transitioned from Index since we can always safely add the class "title-element" to give the view-transition-name: title-element to the heading element. But in the case where we do the reverse transition (from (Detail "1"), to Index), we need to use the "Transition From State".

Integrations

This could be integrated into Elm in a more core way, or more likely into related Elm meta-frameworks like elm-spa, elm-land, elm-pages. I'm planning to integrate this into a new release of elm-pages.

Resources

Running this repo

Proof of concept for the Chrome View Transitions API in Elm.

To run locally, clone and run:

npm install
npm start