Overlays change the app page title under them (Settings shows 'Settings' as the blurred H1 during open/close) #487

Closed
opened 2026-09-30 06:23:14 +00:00 by kayg · 4 comments
Owner

Bug (owner, 2026-09-30, screenshot)

"when settings is opened, the H1 in the app says Settings? i can see it while the overlay animates to appear and disappear? ... why would the app h1 change when any overlay opens?"
While the Settings overlay animates in and out, the blurred app page behind it shows the large title "Settings" instead of the title of the page the User was on (for example "September 2026" or "Inbox").

Expected

An overlay never changes the page under it. The background keeps the exact title, header, sub-view and scroll position of the route the User came from, before, during and after the open and close animations. This applies to every overlay route (Settings, Search, the Inspector, sheets opened by deep link) and to deep-linking straight into /settings/... (the background is then the User's last or default tab, never a "Settings" page).

Likely cause (verify)

The app header title is derived from the current route, and /settings is an overlay route (see the earlier overlay change: /settings was removed from FULLSCREEN_ROUTES, OverlaySurface, overlay.consumeLaunchRoute()). The title source must use the underlying (background) route while an overlay is active. Find the one place the title is computed and fix it there. Do not special-case Settings.

Proof

An e2e opens Settings from Calendar, Mail and Files. It samples the header title text (the DOM, and a screenshot frame mid-animation, open and close) and asserts that it equals the underlying page's title. It also covers a deep link straight to /settings/appearance. Frame strips at 1440 and 390 in both themes. Gates: bun run check, bun run test.

## Bug (owner, 2026-09-30, screenshot) "when settings is opened, the H1 in the app says Settings? i can see it while the overlay animates to appear and disappear? ... why would the app h1 change when any overlay opens?" While the Settings overlay animates in and out, the blurred app page behind it shows the large title "Settings" instead of the title of the page the User was on (for example "September 2026" or "Inbox"). ## Expected An overlay never changes the page under it. The background keeps the exact title, header, sub-view and scroll position of the route the User came from, before, during and after the open and close animations. This applies to every overlay route (Settings, Search, the Inspector, sheets opened by deep link) and to deep-linking straight into `/settings/...` (the background is then the User's last or default tab, never a "Settings" page). ## Likely cause (verify) The app header title is derived from the current route, and `/settings` is an overlay route (see the earlier overlay change: `/settings` was removed from FULLSCREEN_ROUTES, OverlaySurface, `overlay.consumeLaunchRoute()`). The title source must use the underlying (background) route while an overlay is active. Find the one place the title is computed and fix it there. Do not special-case Settings. ## Proof An e2e opens Settings from Calendar, Mail and Files. It samples the header title text (the DOM, and a screenshot frame mid-animation, open and close) and asserts that it equals the underlying page's title. It also covers a deep link straight to `/settings/appearance`. Frame strips at 1440 and 390 in both themes. Gates: `bun run check`, `bun run test`.
Author
Owner

Starting investigation on job/overlay-title-487 from base 0dc772c369.

Starting investigation on job/overlay-title-487 from base 0dc772c3697ea9bd01822c26440c32206d472715.
Author
Owner

Confirmed the title regression with the worktree production SPA and a local server. On Mail at 390 px in light theme, .mode-header .mh-title-text was Inbox before opening Settings and became Settings during the opening transition. The new e2e failed with expected Inbox, actual Settings. The shared shell computes the header from the active route in apps/web/src/routes/+layout.svelte.

Confirmed the title regression with the worktree production SPA and a local server. On Mail at 390 px in light theme, `.mode-header .mh-title-text` was `Inbox` before opening Settings and became `Settings` during the opening transition. The new e2e failed with `expected Inbox, actual Settings`. The shared shell computes the header from the active route in `apps/web/src/routes/+layout.svelte`.
Author
Owner

Implemented Forgejo #487 on job/overlay-title-487.

What changed

  • The app shell captures the complete background header context before route navigation and keeps it while an overlay is active. It retains the page title, sub-view, selected Tab, page actions, and document title together.
  • Cold mode-less app routes use the selected or default Tab until the overlay surface registers. This applies to route overlays generally; it does not special-case Settings.
  • Added a real-server Playwright e2e for Calendar, Mail, Files, and a cold /settings/appearance deep link.
  • Files: apps/web/src/routes/+layout.svelte, apps/web/e2e/overlay-title.mjs, apps/web/package.json.

Proof

  • overlay-title e2e passed: Calendar, Mail and Files at 390, 820, 1440 px in light and dark; frame strips saved in /home/kayg/Developer/calternal-wt/overlay-title-487/artifacts/overlay-title-487
  • Production build: ✓ built in 2m 30s; Wrote site to "build".
  • Uploaded and verified all 24 screenshot strips as issue attachments. They cover each Tab at all three widths in both themes, plus the deep link at each width and theme.

Gate output

bun run check:

$ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
Text sizes and UI shape values use shared role tokens.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/overlay-title-487/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

bun run test:

❯ |unit| src/lib/styles/font-weight-token.test.ts (3 tests | 1 failed) 17944ms
Error: Test timed out in 5000ms.
Test Files  1 failed | 136 passed (137)
      Tests  1 failed | 887 passed (888)
error: script "test" exited with code 1

The isolated diagnostic passed without changing its expectation:

$ vitest run src/lib/styles/font-weight-token.test.ts "--maxWorkers=1"
Test Files  1 passed (1)
      Tests  3 passed (3)
   Duration  1.23s (tests 55%, transform 32%, import 11%, worker 2%)

The full unit run timed out at the existing 5-second limit for the font-token source scan; the focused run completed in 1.23 seconds. The full bun run test gate remains failed. No test expectation changed.

Decisions not specified in DESIGN.md

  • Use the opener’s captured Tab context for in-app overlay navigation. For a cold mode-less route, use the first visible Tab, falling back to Calendar if no Tab is configured.
  • Keep the document title and the related Tab and page-action state on that same context, so the shell does not combine values from the overlay route and the background route.

Head SHA: 064ba6c4a4

Attached screenshots

Implemented Forgejo #487 on `job/overlay-title-487`. ### What changed - The app shell captures the complete background header context before route navigation and keeps it while an overlay is active. It retains the page title, sub-view, selected Tab, page actions, and document title together. - Cold mode-less app routes use the selected or default Tab until the overlay surface registers. This applies to route overlays generally; it does not special-case Settings. - Added a real-server Playwright e2e for Calendar, Mail, Files, and a cold `/settings/appearance` deep link. - Files: `apps/web/src/routes/+layout.svelte`, `apps/web/e2e/overlay-title.mjs`, `apps/web/package.json`. ### Proof - `overlay-title e2e passed: Calendar, Mail and Files at 390, 820, 1440 px in light and dark; frame strips saved in /home/kayg/Developer/calternal-wt/overlay-title-487/artifacts/overlay-title-487` - Production build: `✓ built in 2m 30s`; `Wrote site to "build"`. - Uploaded and verified all 24 screenshot strips as issue attachments. They cover each Tab at all three widths in both themes, plus the deep link at each width and theme. ### Gate output `bun run check`: ```text $ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes and UI shape values use shared role tokens. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/overlay-title-487/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test`: ```text ❯ |unit| src/lib/styles/font-weight-token.test.ts (3 tests | 1 failed) 17944ms Error: Test timed out in 5000ms. Test Files 1 failed | 136 passed (137) Tests 1 failed | 887 passed (888) error: script "test" exited with code 1 ``` The isolated diagnostic passed without changing its expectation: ```text $ vitest run src/lib/styles/font-weight-token.test.ts "--maxWorkers=1" Test Files 1 passed (1) Tests 3 passed (3) Duration 1.23s (tests 55%, transform 32%, import 11%, worker 2%) ``` The full unit run timed out at the existing 5-second limit for the font-token source scan; the focused run completed in 1.23 seconds. The full `bun run test` gate remains failed. No test expectation changed. ### Decisions not specified in DESIGN.md - Use the opener’s captured Tab context for in-app overlay navigation. For a cold mode-less route, use the first visible Tab, falling back to Calendar if no Tab is configured. - Keep the document title and the related Tab and page-action state on that same context, so the shell does not combine values from the overlay route and the background route. Head SHA: 064ba6c4a4ef3161b50cd43aa4d6b791e452454c ### Attached screenshots - [calendar-desktop-1440-paper-light.png](https://git.kayg.org/attachments/5f1fad26-f181-448a-bc6b-4037f95f82da) - [calendar-desktop-1440-tokyo-night-dark.png](https://git.kayg.org/attachments/429450dc-ff46-4cc9-807c-d472d8ea76ef) - [calendar-phone-390-paper-light.png](https://git.kayg.org/attachments/5267ae88-8774-4220-ad99-3e326b939af7) - [calendar-phone-390-tokyo-night-dark.png](https://git.kayg.org/attachments/dde6338a-1ecf-4bf5-8755-ca1661ad4738) - [calendar-tablet-820-paper-light.png](https://git.kayg.org/attachments/98729dd2-f7b7-4de4-8cbf-d894a39bb493) - [calendar-tablet-820-tokyo-night-dark.png](https://git.kayg.org/attachments/25315e70-9063-446f-9667-ee5a527db6c3) - [files-desktop-1440-paper-light.png](https://git.kayg.org/attachments/0239a609-c352-4c96-b4bd-e9cb87fa4cba) - [files-desktop-1440-tokyo-night-dark.png](https://git.kayg.org/attachments/fa7be737-a107-4353-a8ac-aa0f0c740415) - [files-phone-390-paper-light.png](https://git.kayg.org/attachments/a1b85e08-c29f-40bd-9f67-4bc460fdf2de) - [files-phone-390-tokyo-night-dark.png](https://git.kayg.org/attachments/54523f65-e1d2-4a8d-a24e-a7950a389f0a) - [files-tablet-820-paper-light.png](https://git.kayg.org/attachments/70e9fa2a-2995-4007-9135-c3357f0a1052) - [files-tablet-820-tokyo-night-dark.png](https://git.kayg.org/attachments/3c053593-4814-4f9e-9a4b-9a28b1039360) - [mail-desktop-1440-paper-light.png](https://git.kayg.org/attachments/29c208b7-0042-4de6-999b-3b98a8794734) - [mail-desktop-1440-tokyo-night-dark.png](https://git.kayg.org/attachments/4a68627d-4a04-4090-828d-86a2c49c64d9) - [mail-phone-390-paper-light.png](https://git.kayg.org/attachments/95a96372-c9d1-43b4-b979-6159e70c43bc) - [mail-phone-390-tokyo-night-dark.png](https://git.kayg.org/attachments/50f42b6b-208f-4bb5-9995-f2ab7812aed2) - [mail-tablet-820-paper-light.png](https://git.kayg.org/attachments/b4204b37-3c51-4d0e-99e0-13ebd4fdcfbd) - [mail-tablet-820-tokyo-night-dark.png](https://git.kayg.org/attachments/e28cddc0-4ead-414e-8e2a-6da4694643cc) - [settings-deeplink-desktop-1440-paper-light.png](https://git.kayg.org/attachments/6d979ce0-8928-4931-8a4a-771d732180d3) - [settings-deeplink-desktop-1440-tokyo-night-dark.png](https://git.kayg.org/attachments/fce5351f-2c79-4a5c-82d2-1ddefc864146) - [settings-deeplink-phone-390-paper-light.png](https://git.kayg.org/attachments/eaa6f675-c1e3-404d-8c36-75884e16cb03) - [settings-deeplink-phone-390-tokyo-night-dark.png](https://git.kayg.org/attachments/913996f0-82b6-4b8b-9f9c-fd1c9c6c4f73) - [settings-deeplink-tablet-820-paper-light.png](https://git.kayg.org/attachments/b5280d29-1233-48c6-9f3a-4f1a40966e97) - [settings-deeplink-tablet-820-tokyo-night-dark.png](https://git.kayg.org/attachments/28e716d7-d294-41c0-822b-a49de3e09ded)
Author
Owner

Merged into dev at 3c172f73d (merged-tree web gates: 0 errors, 888/888).

Merged into dev at 3c172f73d (merged-tree web gates: 0 errors, 888/888).
kayg closed this issue 2026-09-30 09:39:34 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
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
kayg/calternal#487
No description provided.