Files
sure/app/views/layouts/shared/_htmldoc.html.erb
Abhinav Dhiman cc070853b7 fix: Replace platform-wide broadcast_refresh with sync toast (#1964)
* fix: Replace platform-wide broadcast_refresh with sync toast

Instead of calling family.broadcast_refresh on every sync completion
(which reloads the page for all connected family members), broadcast
a lightweight static toast to the existing notification-tray.

A new sync-toast Stimulus controller handles two cases:
- User is idle (no focused form): auto-reloads after 500ms
- User is mid-form: toast stays visible with a manual Refresh button

This prevents in-progress form state from being wiped when a background
sync fires (e.g. adding a transaction, filling an import form).

The toast partial contains no user-scoped data, so the Current.user nil
constraint in background jobs is no longer a concern.

* fix(a11y): add explicit button types and aria-label to sync toast controls

* fix(sync-toast): improve interaction detection and replace broadcast strategy

- Increase auto-refresh delay from 500ms to 2000ms
- Expand interaction detection to include contentEditable, dialogs, and role="dialog" elements
- Switch from broadcast_append_to to broadcast_replace_to with dedicated #sync-toast target
- Add explicit id="sync-toast" to partial for targeted replacement
- Move sync_toast i18n keys from defaults/en.yml to views/shared/en.yml

* fix(sync-toast): replace hardcoded white icon color with inverse token
2026-05-31 16:05:54 +02:00

46 lines
1.5 KiB
Plaintext

<!DOCTYPE html>
<% theme = Current.user&.theme || "system" %>
<html
lang="en"
data-theme="<%= theme %>"
data-controller="theme viewport"
data-theme-user-preference-value="<%= Current.user&.theme || "system" %>"
class="h-[var(--app-height, 100dvh)] text-primary bg-surface overflow-hidden overscroll-none font-sans <%= @os %>">
<head>
<%= render "layouts/shared/head" %>
<%= yield :head %>
</head>
<body class="h-[var(--app-height)] overflow-hidden antialiased">
<% if Rails.env.development? %>
<button hidden data-controller="hotkey" data-hotkey="t t /" data-action="theme#toggle"></button>
<% end %>
<div class="fixed z-50 top-6 md:top-4 left-1/2 -translate-x-1/2 w-full md:w-80 px-4 md:px-0 mx-auto md:mx-0 md:right-auto pt-[env(safe-area-inset-top)]">
<div id="notification-tray" class="space-y-1 w-full">
<%= render_flash_notifications %>
<div id="sync-toast"></div>
<div id="cta"></div>
</div>
</div>
<% if Current.family %>
<%= turbo_stream_from Current.family %>
<% end %>
<%= turbo_frame_tag "modal" %>
<%= turbo_frame_tag "drawer" %>
<%# Custom overrides for browser's confirm API %>
<%= render "layouts/shared/confirm_dialog" %>
<%= render "impersonation_sessions/super_admin_bar" if Current.true_user&.super_admin? && show_super_admin_bar? %>
<%= render "impersonation_sessions/approval_bar" if Current.true_user&.impersonated_support_sessions&.initiated&.any? %>
<%= yield %>
</body>
</html>