From 15f95067beec17d2e0039c1353fd4864e8dcd344 Mon Sep 17 00:00:00 2001 From: Adib Hanna Date: Sun, 1 Nov 2026 12:32:26 -0600 Subject: [PATCH] fix(mobile): the status bar stays clear on iOS 27, and views run to the bottom edge ZenNotes/zennotes#1035: on iOS 27.2 in dark mode a whitish band covered the status bar until the keyboard opened, and a blank strip sat under every view. The band is the system's top scroll edge effect on the web view. Apps built with the iOS 27 SDK get the new design whatever UIDesignRequiresCompatibility says, so the WKWebView's scroll view carries the effect, and its blur reaches past the transparent page into the window behind it. That window's color is the keyboard backdrop's, set at boot and on keyboardWillShow only. index.html's pre-boot theme takes the stored themeId as is, and Auto keeps the id of the variant picked in light, so a dark-mode launch painted the window white before core resolved the theme to dark; nothing repainted it until a keyboard opened, which is why the band went away then. On an iOS 27.2 simulator with Auto and the Apple theme the band's pixels match the reporter's screenshot. ZNViewController hides the web view's four edge effects: the page draws its own chrome and never scrolls the document, so they have nothing to mark, and this alone clears the band whatever the window's color. The backdrop also follows the theme now: watchThemeBackdrop() re-reads --z-bg when core changes the theme attributes on or its managed styles in , once a frame, and sends a color only when it changed, so the window around the rounded keyboard matches too. The strip was the app shell's own bottom padding, 0.75rem plus the home indicator. The shell no longer pads the bottom: views run under the indicator to the screen edge, and each view's main scroller (a flex-1 overflow element) ends with that clearance as a spacer, so its last line still scrolls clear. The editor already ends with core's padding. The Kanban board pads itself so its columns stop where they did; side panels and the note-list column pad themselves and add no spacer; with the keyboard up the clearance is 0, as the padding was; and Cloud's attention row, now the last thing in the shell, carries the clearance under its 44px so its action and the circle stay put. The Android shell keeps its rules: the band needs UIKit's edge effects, and its always-on Cloud status row owns the bottom inset there. Verified on the simulator through the page, touch and lldb; the notes are in docs/status-bar-overlay-validation-2026-11-01.md. --- ...tatus-bar-overlay-validation-2026-11-01.md | 133 ++++++++++++++++++ ios/App/App/ZNViewController.swift | 19 +++ src/bridge/keyboard-backdrop.ts | 35 ++++- src/main.tsx | 9 +- src/ui-mobile/mobile-layout.test.ts | 33 ++++- src/ui-mobile/mobile.css | 45 +++++- 6 files changed, 262 insertions(+), 12 deletions(-) create mode 100644 docs/status-bar-overlay-validation-2026-11-01.md diff --git a/docs/status-bar-overlay-validation-2026-11-01.md b/docs/status-bar-overlay-validation-2026-11-01.md new file mode 100644 index 0000000..2d153e5 --- /dev/null +++ b/docs/status-bar-overlay-validation-2026-11-01.md @@ -0,0 +1,133 @@ +# Status bar overlay and bottom strip: verification, 1 November 2026 + +Branch `fix/ios-overlay-1035`, cut from `origin/main` at e2bf684 (1.35.0, +build 54). Committed locally, not pushed. Changes: `ios/App/App/ZNViewController.swift`, +`src/bridge/keyboard-backdrop.ts`, `src/main.tsx`, `src/ui-mobile/mobile.css` +and the layout contracts in `src/ui-mobile/mobile-layout.test.ts`. No +app-core change and no Capacitor config change. + +Report: ZenNotes/zennotes#1035 (@Christian-SC26), iPhone 1.35.0 on iOS 27.2 +in dark mode. A whitish, translucent band covers the status bar; it goes away +once the keyboard opens. A blank strip sits at the bottom of the screen. + +## Cause + +**The band is the iOS 27 scroll edge effect on the web view.** Apps built +with the iOS 27 SDK get the current design whatever +`UIDesignRequiresCompatibility` says (the key added for #631 only works on +iOS 26), so the WKWebView's scroll view carries the system's top edge effect +(`style=automatic backgroundCapture=sampled`, read with lldb from the running +1.35.0 build). The effect is a progressive blur over the top safe area. Near +the screen edge it samples past the page, which is transparent +(`ios.backgroundColor` `#00000000`), into the UIWindow behind it. + +**The window's color is the keyboard backdrop's**, and that was only set at +boot and on `keyboardWillShow`. At boot `index.html`'s pre-boot script sets +`data-theme` from the stored `themeId` as is, even in Auto mode, and Auto +keeps the id of the variant the user picked (`apple-light`, say). The boot +sync read that light theme's `--z-bg` (white) into the window; core then +resolved Auto to `apple-dark`, and nothing repainted the window. The edge +effect blurred white into the status bar. Opening the keyboard ran the sync +again, so the window turned dark and the band went away: exactly the report. +The same thing happens without a cold launch when Auto follows the system +from light to dark while the app runs, or when a theme is picked in Settings. + +Measured column, top 60 pt, dark Apple theme: the reporter's screenshot runs +126, 125, 124, 121, 117, 111, 102, 87, 69, 51, 38, 30, 28 (every 5 pt); the +simulator before the fix runs 127, 127, 125, 122, 119, 114, 105, 94, 77, 59, +45, 33, 29. + +**The bottom strip is the shell's own padding.** `.zn-app-shell` padded +`0.75rem + env(safe-area-inset-bottom)` under every view (46 pt on an iPhone +16 Pro), so the note stopped at a hard line well above the home indicator. + +## Fix + +- **Native:** `ZNViewController` hides the web view's four scroll edge effects + (iOS 26 and later). The page draws its own chrome edge to edge and never + scrolls the document, so the effects have nothing to mark. This alone + removes the band, whatever color the window has. +- **Backdrop follows the theme:** `watchThemeBackdrop()` replaces the one-off + boot sync. It re-reads `--z-bg` whenever core changes `data-theme` or + `data-theme-mode` on ``, or the managed `