mirror of
https://github.com/we-promise/sure.git
synced 2026-08-05 16:42:18 +00:00
* fix(accounts): make the sync toolbar and toast agree, fix toast overlap The Accounts page's own sync toolbar (refresh icon, "Cancel sync") and the global sync-complete toast were three inconsistently-styled, disconnected pieces of UI representing one action, and the toast overlapped the page's own header instead of sitting near it. - "Cancel sync" was hand-rolled markup instead of a DS::Button, unlike its sibling refresh icon right next to it — now both are DS::Button (:ghost). - The refresh icon just went `disabled` with no visible "working" state — now shows a spinning loader-circle while a family sync is in progress, matching the pattern already used in provider_sync_summary.html.erb. - The toolbar was plain server-rendered HTML with no way to know a sync finished, so it stayed stuck showing "still syncing" indefinitely next to a toast now saying otherwise. Family::SyncCompleteEvent now broadcasts a second replace target for the toolbar alongside the existing toast replace, so both resolve together. - The notification tray was a <body>-level fixed overlay centered on the full viewport, but every layout that renders it has a sidebar of some kind — so it never actually centered on the visible content pane, and landed on top of the settings-layout header. It now renders in-flow at the top of each layout's own content region (opt-in via notification_tray_inline, since the simpler single-column layouts don't have this mismatch and are unaffected). - Added the Catalan sync_toast/cancel_sync strings that were missing entirely, which is why the toast/toolbar showed English text on an otherwise-Catalan page. Verified live in a real browser via a new system test covering the idle, syncing, and cancel-flash states, plus a model test on the new broadcast target. * fix(accounts): keep the tray a floating overlay, sidebar-aware instead Codex on this PR: with the tray as first-child-of-scrollable-main, a notification delivered while scrolled down is inserted above the viewport and stays unseen — breaking the sync toast's manual-refresh path specifically, since sync_toast_controller.js suppresses auto-refresh while a form is focused and relies on the toast being visible to offer that manual refresh. Reverts the tray to a position: fixed overlay for every layout (so it can't be scrolled out of view), and fixes the actual bug that made it overlap the accounts toolbar in the first place — a ResizeObserver on <main> centers it on the real content pane instead of the viewport, for the two layouts with a sidebar (application, settings passed via sidebar_aware:). The five single-column layouts are untouched; for those, viewport-center already is content-pane-center. One trap worth flagging: this app renders turbo_refreshes_with method: :morph, and idiomorph resets any inline style a client script set that isn't in the freshly-fetched HTML — including the JS-set `left`. data-turbo-permanent looked like the fix but isn't: it invokes idiomorph's node-identity matching (same id preserved across ANY morphed page), which broke navigation once the id existed on structurally different layouts (app vs settings) — a real, reproduced bug, caught by the system test before it shipped. Went with the narrower turbo:before-morph-attribute event instead, which blocks only the `style` attribute on this one element, with no node-identity system involved. Rewrote the system test's positioning assertion to match: it now asserts the tray centers on <main> rather than sitting above the page header, since a fixed overlay was never going to satisfy the latter by construction. Verified: full bin/rails test (6023 runs, 0 failures), rubocop, erb_lint, brakeman (0 warnings) all clean. Live-verified in a browser across both sidebar-aware layouts and a simple layout, including the full cancel-sync -> morph -> re-render cycle. * fix(accounts): use declarative Stimulus action for morph-attribute guard Replace the manual addEventListener/removeEventListener pair for turbo:before-morph-attribute with a data-action, per the repo's declarative-actions convention. Same element, same listener — just no manual lifecycle management.
50 lines
2.2 KiB
Plaintext
50 lines
2.2 KiB
Plaintext
<%= render "layouts/shared/htmldoc", sidebar_aware: true 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 id="settings-nav-container" data-controller="preserve-scroll" 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" data-notification-tray-target="main">
|
|
<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 %>
|