Files
sure/app/views/layouts/settings.html.erb
Guillem Arias Fauste 5f391f7fff fix(settings): preserve content scroll position per page across navigation (#2277)
Settings nav items are plain Turbo Drive links (full-body visits); Turbo only
restores window scroll, so the nested overflow-y-auto content container snapped
to the top on every settings navigation.

Add a settings-scroll Stimulus controller that saves/restores the content scroll
keyed by pathname: returning to a page restores its scroll, a new page opens at
the top, and a same-page re-render (settings form auto-submit) keeps scroll.
Distinct from the nav's preserve-scroll controller, which keys by element id to
intentionally carry one position across pages.

Verified live: scroll 250 on Preferences -> Appearance opens at top -> back to
Preferences restores 250.
2026-06-11 15:52:07 +02:00

50 lines
2.1 KiB
Plaintext

<%= render "layouts/shared/htmldoc" do %>
<div class="flex flex-col md:flex-row h-full bg-surface pt-[env(safe-area-inset-top)]">
<%= link_to t("layouts.application.skip_to_main"), "#main",
class: "sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-50 focus:px-3 focus:py-2 focus:rounded-lg focus:bg-container focus:text-primary focus:shadow-border-xs" %>
<div class="w-full md:w-auto md:min-w-64 shrink-0 md:h-full md:overflow-y-auto border-divider md:border-r">
<div class="p-4">
<%= render "settings/settings_nav" %>
</div>
</div>
<main id="main" class="grow flex h-full">
<div class="relative max-w-4xl mx-auto flex flex-col w-full h-full">
<div data-controller="settings-scroll" class="grow flex flex-col overflow-y-auto overflow-x-hidden overscroll-contain [-webkit-overflow-scrolling:touch]">
<div class="sticky top-0 z-10 px-3 md:px-10 pt-1.5 md:pt-3 pb-3 bg-surface border-b border-tertiary shrink-0">
<% if content_for?(:breadcrumbs) %>
<%= yield :breadcrumbs %>
<% else %>
<%= render "layouts/shared/breadcrumbs", breadcrumbs: breadcrumbs %>
<% end %>
<div class="flex items-center justify-between gap-4 mt-1.5 min-h-9">
<% if content_for?(:page_title) %>
<h1 class="text-primary text-xl font-medium">
<%= content_for :page_title %>
</h1>
<% else %>
<div></div>
<% end %>
<% if content_for?(:page_actions) %>
<div class="flex items-center gap-2 shrink-0">
<%= yield :page_actions %>
</div>
<% end %>
</div>
</div>
<div class="grow space-y-4 px-3 md:px-10 pb-20 pt-4">
<%= yield %>
<%= settings_nav_footer_mobile %>
<div class="my-4">
<%= settings_nav_footer %>
</div>
</div>
</div>
</div>
</main>
</div>
<% end %>