Skip to content

Commit

Permalink
Document page refreshes with morphing (#160)
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgemanrubia authored Feb 7, 2024
1 parent f1a52cb commit 0b2c287
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 1 deletion.
82 changes: 82 additions & 0 deletions _source/handbook/03_page_refreshes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
permalink: /handbook/page_refreshes.html
description: "Turbo can perform smooth page refreshes with morphing and scroll preservation."
---

# Smooth page refreshes with morphing

[Turbo Drive](/handbook/drive.html) makes navigation faster by avoiding full-page reloads. But there is a scenario where Turbo can raise the fidelity bar further: loading the current page again (page refresh).

A typical scenario for page refreshes is submitting a form and getting redirected back. In such scenarios, sensations significantly improve if only the changed contents get updated instead of replacing the `<body>` of the page. Turbo can do this on your behalf with morphing and scroll preservation.

${toc}

## Morphing

You can configure how Turbo handles page refresh with a `<meta name="turbo-refresh-method">` in the page's head.

```html
<head>
...
<meta name="turbo-refresh-method" content="morph">
</head>
```

The possible values are `morph` or `replace` (the default). When it is `morph,` when a page refresh happens, instead of replacing the page's `<body>,` Turbo will only update the DOM elements that have changed, keeping the rest untouched. This approach delivers better sensations because it keeps the screen state.

Under the hood, Turbo uses the fantastic [idiomorph library](https://github.com/bigskysoftware/idiomorph).

## Scroll preservation

You can configure how Turbo handles scrolling with a `<meta name="turbo-refresh-scroll">` in the page's head.

```html
<head>
...
<meta name="turbo-refresh-scroll" content="preserve">
</head>
```

The possible values are `preserve` or `reset` (the default). When it is `preserve`, when a page refresh happens, Turbo will keep the page's vertical and horizontal scroll.

## Exclude sections from morphing

Sometimes, you want to ignore certain elements while morphing. For example, you might have a popover that you want to keep open when the page refreshes. You can flag such elements with `data-turbo-permanent`, and Turbo won't attempt to morph them.

```html
<div data-turbo-permanent>...</div>
```

## Turbo frames

You can use [turbo frames](/handbook/frames.html) to define regions in your screen that will get reloaded using morphing when a page refresh happens. To do so, you must flag those frames with `refresh="morph"`.

```html
<turbo-frame id="my-frame" refresh="morph">
...
</turbo-frame>
```

With this mechanism, you can load additional content that didn't arrive in the initial page load (e.g., pagination). When a page refresh happens, Turbo won't remove the frame contents; instead, it will reload the turbo frame and render its contents with morphing.

## Broadcasting page refreshes

There is a new [turbo stream action](/handbook/streams.html) called `refresh` that will trigger a page refresh:

```html
<turbo-stream action="refresh"></turbo-stream>
```

Server-side frameworks can leverage these streams to offer a simple but powerful broadcasting model: the server broadcasts a single general signal, and pages smoothly refresh with morphing.

You can see how the [`turbo-rails`](https://github.com/hotwired/turbo-rails) gem does it for Rails:

```ruby
# In the model
class Calendar < ApplicationRecord
broadcasts_refreshes
end

# View
turbo_stream_from @calendar
```
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 3 additions & 1 deletion _source/reference/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The following data attributes can be applied to elements to customize Turbo's be
* `data-turbo-track="reload"` tracks the element's HTML and performs a full page reload when it changes. Typically used to [keep `script` and CSS `link` elements up-to-date](/handbook/drive#reloading-when-assets-change).
* `data-turbo-frame` identifies the Turbo Frame to navigate. Refer to the [Frames documentation](/reference/frames) for further details.
* `data-turbo-action` customizes the [Visit](/handbook/drive#page-navigation-basics) action. Valid values are `replace` or `advance`. Can also be used with Turbo Frames to [promote frame navigations to page visits](/handbook/frames#promoting-a-frame-navigation-to-a-page-visit).
* `data-turbo-permanent` [persists the element between page loads](/handbook/building#persisting-elements-across-page-loads). The element must have a unique `id` attribute.
* `data-turbo-permanent` [persists the element between page loads](/handbook/building#persisting-elements-across-page-loads). The element must have a unique `id` attribute. It also serves to exclude elements from being morphed when using [page refreshes with morphing](/handbook/page_refreshes.html)
* `data-turbo-temporary` removes the element before the document is cached, preventing it from reappearing when restored.
* `data-turbo-eval="false"` prevents inline `script` elements from being re-evaluated on Visits.
* `data-turbo-method` changes the link request type from the default `GET`. Ideally, non-`GET` requests should be triggered with forms, but `data-turbo-method` might be useful where a form is not possible.
Expand All @@ -38,3 +38,5 @@ The following `meta` elements, added to the `head`, can be used to customize cac
* `<meta name="turbo-cache-control">` to [opt out of caching](/handbook/building#opting-out-of-caching).
* `<meta name="turbo-visit-control" content="reload">` will perform a full page reload whenever Turbo navigates to the page, including when the request originates from a `<turbo-frame>`.
* `<meta name="turbo-root">` to [scope Turbo Drive to a particular root location](/handbook/drive#setting-a-root-location).
* `<meta name="turbo-refresh-method" content="morph">` will configure [page refreshes with morphing](/handbook/page_refreshes.html).
* `<meta name="turbo-refresh-scroll" content="preserve">` will enable [scroll preservation during page refreshes](/handbook/page_refreshes.html).
8 changes: 8 additions & 0 deletions _source/reference/frames.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ Like an eager-loaded frame, but the content is not loaded from `src` until the f
</turbo-frame>
```

## Frame that will get reloaded with morphing during page refreshes

```html
<turbo-stream action="refresh">
...
</turbo-stream>
```

# Attributes, properties, and functions

The `<turbo-frame>` element is a [custom element][] with its own set of HTML
Expand Down

0 comments on commit 0b2c287

Please sign in to comment.