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

Optimistic UI with Turbo 8 Morphs
26 March 2024

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

Turbo Drive - Conditional InstantClick
13 February 2024

Conditionally opt out of Turbo Drive InstantClick using the Strategy pattern

Turbo Drive - Re-Use the Turbo Progress Bar
18 July 2023

Update the progress bar according to some background process' progress.

essential