Skip to content

Conversation

@seanpdoyle
Copy link
Contributor

I have a page where I am using Turbo morph. when I submit a form and
redirect I would like to reset the scroll, but if a refresh is triggered
by a broadcast I would like to preserve teh scroll. Is that possible ?

#turbo Discord

This commit expands the set of attributes for <turbo-stream action="refresh"> to include [method] and [scroll] (in addition to [request-id]). These attributes correspond directly to the turbo-refresh-prefixed <meta> element elements that control morphing and scroll preservation.

When present on the <turbo-stream action="refresh">, their values are forward along to the Session.refresh method call, which in turn encodes them into Visit options under the refresh key. Those options are then used during Visit instantiation, and transformed into .refresh properties.

At render time, the PageRenderer attempts to read the refresh method and scroll preservation settings with the following precedence:

  1. read from the corresponding Visit.refresh property (possibly null)
  2. read from the corresponding <meta name="turbo-..."> element (possibly null)

If no value is provided, fallback to the default ({ method: "replace", scroll: "reset" }).

@seanpdoyle
Copy link
Contributor Author

@adrienpoly I've opened this in response to our conversation in Discord.

@seanpdoyle
Copy link
Contributor Author

seanpdoyle commented Feb 28, 2024

I feel that the [method] and [scroll] attributes matching the turbo-refresh-prefixed meta element [name] attributes is appropriate.

I'm less confident about the Visit options key (and resulting property name). The "public API" boundaries of Visit options are currently unclear. If we intend for these keys to be private and for internal use only, the name isn't important to decide upon. If they're intended to be public, I think it's important to workshop and appropriate name and structure.

@jorgemanrubia does this seem like a conservative enough expansion of Morph Refresh support?

@adrienpoly
Copy link
Member

@adrienpoly I've opened this in response to our conversation in Discord.

Thanks, I am trying to understand how I could leverage in my Rails app and it is a bit unclear.

A simplify version of what I have is

class Post 
  broadcast_refreshes
  ...
end

and a view view

<%= turbo_stream_from @post %>
<%= turbo_refreshes_with method: :morph, scroll: :reset %>

<form ....></form>

The form redirect to this page with a scroll reset and I would like to preserve the scroll when the refresh is triggered by a broadcast.

Looking at your proposal I am not sure how I should set the turbo-stream attributes?

Would it be something like this?

<%= turbo_stream_from @post, scroll: :preserve %>

or at the model level?

Thanks

@seanpdoyle
Copy link
Contributor Author

or at the model level?

To support scroll resets from redirects during a form submission, you could continue to render the <meta name="turbo-refresh-scroll" content="reset">, or omit the element entirely.

To support scroll preservation from broadcasts, the idea would be to broadcast the <turbo-stream> element with the configuration encoded directly into the element.

Since this change must be made separate from the Rails code, that support is still unclear and to be determined. One possibility could be to extend broadcast_refreshes to accept HTML attribute options:

broadcast_refreshes scroll: :preserve

Another approach might be to keep broadcast_refreshes generic and simple like it currently is, but change broadcast_refresh_to and broadcast_refresh_later_to to accept the attributes in the same way that the other stream broadcast methods accept :target, :targets, etc.

@seanpdoyle seanpdoyle force-pushed the refresh-stream-attributes branch from 56ffe7d to 99d0755 Compare March 29, 2024 23:37
@seanpdoyle seanpdoyle force-pushed the refresh-stream-attributes branch from 99d0755 to 2ccb92e Compare July 12, 2024 19:09
@seanpdoyle
Copy link
Contributor Author

@jorgemanrubia are you able to review this proposal?

> I have a page where I am using Turbo morph. when I submit a form and
> redirect I would like to reset the scroll, but if a refresh is triggered
> by a broadcast I would like to preserve teh scroll. Is that possible ?
>
> [#turbo Discord][discord]

This commit expands the set of attributes for `<turbo-stream
action="refresh">` to include `[method]` and `[scroll]` (in addition to
`[request-id]`). These attributes correspond directly to the
[`turbo-refresh`-prefixed `<meta>` element][meta] elements that control
morphing and scroll preservation.

When present on the `<turbo-stream action="refresh">`, their values are
forward along to the `Session.refresh` method call, which in turn
encodes them into Visit options under the `refresh` key. Those options
are then used during `Visit` instantiation, and transformed into
`.refresh` properties.

At render time, the `PageRenderer` attempts to read the refresh method
and scroll preservation settings with the following precedence:

1. read from the corresponding `Visit.refresh` property (possibly null)
2. read from the corresponding `<meta name="turbo-...">` element (possibly null)

If no value is provided, fallback to the default (`{ method: "replace",
scroll: "reset" }`).

[discord]: https://discord.com/channels/988103760050012160/1044659721229054033/1212443786270212167
[meta]: https://turbo.hotwired.dev/handbook/page_refreshes#morphing
@seanpdoyle seanpdoyle force-pushed the refresh-stream-attributes branch from 2ccb92e to ffb1d8d Compare November 2, 2025 00:57
Copy link
Member

@jorgemanrubia jorgemanrubia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one @seanpdoyle

@jorgemanrubia jorgemanrubia merged commit 10ebcb2 into hotwired:main Nov 3, 2025
1 check passed
@seanpdoyle seanpdoyle deleted the refresh-stream-attributes branch November 3, 2025 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants