Customize the reconnection modal, prevent it from appearing when bringing the PWA from the background into the foreground #74

Closed
opened 2026-08-08 02:16:45 +00:00 by Grandiras · 2 comments
Owner
No description provided.
Collaborator

🤖 On it — follow along in the action run; the reply will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the task runs.

🤖 On it — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/216); the reply will link the full session transcript. 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/issue-74/run-216.md) — updating every ~5 minutes while the task runs.
Collaborator

Pushed as claude/issue-74.

Branch claude/issue-74compare against main.

What I found

The scheduling half of this already landed with #36: ReconnectModal.razor.js holds the dialog back so a reconnect that lands inside the grace window — every return to a backgrounded PWA — shows nothing. That still works. Two things were undone, and the second one was quietly undoing the first.

1. The dialog was still the framework's, in both themes. Styling for it existed in app.css and never reached the screen: the component shipped with the template's scoped ReconnectModal.razor.css beside it, and a scoped selector carries an extra attribute — #components-reconnect-modal[b-…] outranks #components-reconnect-modal no matter which file loads last. Measured against the real stylesheets, before the change:

light dark
surface #ffffff (stock) #ffffff (stock) — with --fg text on it, i.e. near-white on white
button #6b9ed2 (stock blue) #6b9ed2
radius 8px 8px

2. The stylesheet could put the dialog on screen without anyone opening it. blazor.web.js marks its progress with classes on the <dialog> as well as with the events the script listens to, and the template turned two of them — components-reconnect-retrying and components-reconnect-failed — into display: block on the dialog itself, which overrides the UA's display: none for a dialog nobody opened. So the second reconnect attempt painted an 82px box into the top of the page, outside the top layer, with no backdrop and no focus, while the script was deliberately keeping it off screen. showModal() was never called, so every existing test was blind to it. It also carried transition: display 0.5s allow-discrete, which keeps a closed dialog painted for a beat after close() — the same flash from the other end.

What I changed

  • Deleted ReconnectModal.razor.css; app.css's Reconnect modal section is now the single home, so the specificity trap can't come back. Nothing in CSS decides whether the dialog is on screen any more — the state classes only choose which line an open one shows.
  • Restyled from the tokens: --bg-1 on --radius with --shadow-xl, the app's .btn-primary pill, the board's own .spinner (two brand bars drifting like the streamlines in the mark) instead of the blue rings, a two-tier message (what happened / what to do), no backdrop blur below 600px for .modal-backdrop's reason, reduced-motion honoured, and no UA focus ring drawn as a black rectangle across the rounded corners.
  • Two new e2e tests that come at it from the side showModal-counting can't reach: each state class on a closed dialog must stay off screen, and the painted surface/button must equal what --bg-1/--brand resolve to in each theme (compared against the tokens, so retuning the palette isn't a failing test).
  • Updated the Reconnecting section of CLAUDE.md with the third piece and why re-adding a scoped stylesheet is the trap.

Verified

This CI container has no podman/docker, so I installed the .NET 10 SDK and Postgres and ran the app directly on :8090 in Development against the real Playwright suite.

  • dotnet build Ponente.sln — clean (only the pre-existing Calendar.razor:266 CS8604 warning).
  • dotnet test165 passed.
  • reconnect.spec.js7/7 passed, including the four pre-existing ones. Both new tests fail on the code they replace (rgb(107,158,210) vs brand rgb(124,58,237); the closed dialog computing display: block for retrying/failed) — I stashed the fix, rebuilt and re-ran to confirm that.
  • All five states render exactly the right line, and none of them shows a closed dialog; checked in light and dark, desktop and phone, plus screenshots.
  • prefs.spec.js, i18n.spec.js — pass. board.spec.js + mobile.spec.js — 44 passed, 3 failed (Escape key closes the card modal, hamburger menu closes when clicking outside, card tags stay labels…). Those three fail identically on unmodified main in this environment — the teardown helper can't reach the DB without a container engine, so the board silts up between runs. Not from this change, but worth a run against a real compose stack before merging.

⏱ 21m 26s · 105 turns · tokens: 161.8k in / 58.9k out (+12125.2k cache-read)
📜 Full session transcript
→ Opened PR: #82

Pushed as `claude/issue-74`. Branch **`claude/issue-74`** — [compare against main](https://git.grandiras.net/Grandiras/Ponente/compare/main...claude/issue-74). ## What I found The *scheduling* half of this already landed with #36: `ReconnectModal.razor.js` holds the dialog back so a reconnect that lands inside the grace window — every return to a backgrounded PWA — shows nothing. That still works. Two things were undone, and the second one was quietly undoing the first. **1. The dialog was still the framework's, in both themes.** Styling for it existed in `app.css` and never reached the screen: the component shipped with the template's scoped `ReconnectModal.razor.css` beside it, and a scoped selector carries an extra attribute — `#components-reconnect-modal[b-…]` outranks `#components-reconnect-modal` no matter which file loads last. Measured against the real stylesheets, before the change: | | light | dark | |---|---|---| | surface | `#ffffff` (stock) | `#ffffff` (stock) — with `--fg` text on it, i.e. **near-white on white** | | button | `#6b9ed2` (stock blue) | `#6b9ed2` | | radius | `8px` | `8px` | **2. The stylesheet could put the dialog on screen without anyone opening it.** `blazor.web.js` marks its progress with classes on the `<dialog>` as well as with the events the script listens to, and the template turned two of them — `components-reconnect-retrying` and `components-reconnect-failed` — into `display: block` **on the dialog itself**, which overrides the UA's `display: none` for a dialog nobody opened. So the second reconnect attempt painted an 82px box into the top of the page, outside the top layer, with no backdrop and no focus, while the script was deliberately keeping it off screen. `showModal()` was never called, so every existing test was blind to it. It also carried `transition: display 0.5s allow-discrete`, which keeps a *closed* dialog painted for a beat after `close()` — the same flash from the other end. ## What I changed - Deleted `ReconnectModal.razor.css`; `app.css`'s *Reconnect modal* section is now the single home, so the specificity trap can't come back. Nothing in CSS decides whether the dialog is on screen any more — the state classes only choose which line an open one shows. - Restyled from the tokens: `--bg-1` on `--radius` with `--shadow-xl`, the app's `.btn-primary` pill, the board's own `.spinner` (two brand bars drifting like the streamlines in the mark) instead of the blue rings, a two-tier message (what happened / what to do), no backdrop blur below 600px for `.modal-backdrop`'s reason, reduced-motion honoured, and no UA focus ring drawn as a black rectangle across the rounded corners. - Two new e2e tests that come at it from the side `showModal`-counting can't reach: each state class on a *closed* dialog must stay off screen, and the painted surface/button must equal what `--bg-1`/`--brand` resolve to in each theme (compared against the tokens, so retuning the palette isn't a failing test). - Updated the **Reconnecting** section of `CLAUDE.md` with the third piece and why re-adding a scoped stylesheet is the trap. ## Verified This CI container has no podman/docker, so I installed the .NET 10 SDK and Postgres and ran the app directly on `:8090` in Development against the real Playwright suite. - `dotnet build Ponente.sln` — clean (only the pre-existing `Calendar.razor:266` CS8604 warning). - `dotnet test` — **165 passed**. - `reconnect.spec.js` — **7/7 passed**, including the four pre-existing ones. Both new tests **fail on the code they replace** (`rgb(107,158,210)` vs brand `rgb(124,58,237)`; the closed dialog computing `display: block` for `retrying`/`failed`) — I stashed the fix, rebuilt and re-ran to confirm that. - All five states render exactly the right line, and none of them shows a closed dialog; checked in light and dark, desktop and phone, plus screenshots. - `prefs.spec.js`, `i18n.spec.js` — pass. `board.spec.js` + `mobile.spec.js` — 44 passed, 3 failed (`Escape key closes the card modal`, `hamburger menu closes when clicking outside`, `card tags stay labels…`). Those three fail identically on unmodified `main` in this environment — the teardown helper can't reach the DB without a container engine, so the board silts up between runs. Not from this change, but worth a run against a real compose stack before merging. --- ⏱ 21m 26s · 105 turns · tokens: 161.8k in / 58.9k out (+12125.2k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/issue-74/run-216.md) → Opened PR: https://git.grandiras.net/Grandiras/Ponente/pulls/82
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Grandiras/Ponente#74
No description provided.