Turbo Drive - Custom Rendering

Completely customize Turbo Drive's rendering process.

View Solution on Patreon
Turbo Drive - Custom Rendering

Premise

On top of pausing rendering and resuming it (see previous challenge), Turbo Drive also exposes a render method to overwrite in the turbo:before-render event. Using the current and new body element, you can use this to provide a custom segue between the two.

Browse through the page_renderer source to get an idea of how this is done in the default implementation:

  1. Check if the requested page will render. This is generally true, except for a redirect, for example.
  2. Replace the body, while preserving permanent elements.
  3. To do this, first activate it, by adopting the new body into the DOM
  4. Finally render the new element.

The Turbo guide uses morphdom as a replacement mechanism, but you are of course free to implement any custom logic here.

🐉 Here be dragons! Be aware that now you are fully in charge to implement the page transition on your own, including edge cases like activating new script elements.

Starting Point

The following StackBlitz example includes two pages (index.html and page2.html) each containing an image and a <ul> acting as a simple navigation. In app.js, there’s some boilerplate code introducing a turbo:before-render event listener. The event.detail.render method you have to implement is already stubbed out. Your challenge is to fork this StackBlitz project and code your own rendering solution. Look below for some challenges you could tackle.

By the way, to add a certain JavaScript package to your importmaps, you can use https://generator.jspm.io/.

Challenges

  • Can you swap out the navigation, but add a nice image transition? (below is an example GIF of how that could look using fancy css filters and GSAP.)
  • Try to implement morphdom, and explore all the options (including onElUpdated and other callbacks)
  • Try to add a third page. Does your implementation still work?

Caveats

  • Again, you have to deal with cache restoration visits. Check <html data-turbo-preview> or opt out of caching altogether.

Teasers

In your app, this could be implemented in a custom stimulus controller, for example, and put onto the body element:

<body data-controller="image-transition" data-action="turbo:before-render->image-transition#swap">
export default class extends Controller {
  swap(event) {
    event.detail.render = (currentElement, newElement) => {
      // rendering logic
    }
  }
}

This way, you could also parameterize the rendering logic by adding Stimulus values to the controller.

More from

Turbo Drive - Swiper-like View Transitions
19 November 2024

Use the View Transitions API to drive powerful native-like animations

Turbo Drive - Use ULIDs for Optimistic UI
13 August 2024

Render deterministic optimistic UI elements using client-side ULIDs

Optimistic UI with Turbo 8 Morphs
26 March 2024

Provide Optimistic UI updates using inline Turbo Stream Actions, and reconcile using Turbo 8 Morphs

essential