fix(ui): native safe-area under Android 15+ edge-to-edge (WebView < 140)

targetSdk 36 forces edge-to-edge, so the WebView draws behind the system
bars. On Android WebView < 140, env(safe-area-inset-*) wrongly reports 0, so
the app chrome (which only read env()) drew under the status bar (top nav
untappable) and the gesture-nav home indicator (the game's centre Hint button
intercepted; side buttons fine). Capacitor 8's SystemBars core plugin (built
into @capacitor/core, insetsHandling:'css' by default) injects the correct
--safe-area-inset-* values on every WebView; consume them ahead of env():

  --tg-safe-*: var(--safe-area-inset-*, env(safe-area-inset-*, 0px))

Web / PWA / Telegram / VK are unchanged (--safe-area-inset-* is unset there,
so it falls back to env()). Verified on-device (Pixel_10 / API 37) via the
injected var — the emulator's auto-updated WebView 149 hides the env() bug,
so the visual alone won't reproduce it.
This commit is contained in:
Ilia Denisov
2026-07-12 18:58:07 +02:00
parent 0eb72ba955
commit 4a0689a4ac
4 changed files with 41 additions and 15 deletions
+13 -9
View File
@@ -54,16 +54,20 @@
/* Height Telegram's native nav overlays at the top in fullscreen; set from the SDK's
content-safe-area inset, 0 elsewhere. */
--tg-content-top: 0px;
/* Device safe-area top (the notch); inside Telegram TG's own nav controls sit between it and
--tg-content-top, so the in-app header aligns to that band. Inside Telegram these are set from
the SDK (lib/app.svelte.ts); elsewhere they fall back to the CSS env() safe area, so a VK Mini
App / Capacitor / PWA webview clears the device cut-outs too (a plain browser tab reports 0). */
--tg-safe-top: env(safe-area-inset-top, 0px);
/* Device safe-area top (the notch / status bar); inside Telegram TG's own nav controls sit between
it and --tg-content-top, so the in-app header aligns to that band. Inside Telegram these are set
from the SDK (lib/app.svelte.ts); on the native Capacitor build the value is the SystemBars core
plugin's injected --safe-area-inset-* — correct on EVERY Android WebView, including the < 140
versions where env(safe-area-inset-*) wrongly reports 0 under Android's mandatory edge-to-edge and
the app chrome would otherwise draw under the system bars. It falls back to the CSS env() safe area
on iOS / PWA / a plain browser tab (0 there). */
--tg-safe-top: var(--safe-area-inset-top, env(safe-area-inset-top, 0px));
/* Device safe-area bottom / sides (home indicator; landscape notch) — the screen pads its bottom
and left/right edges by these so content clears the cut-outs (e.g. the VK mobile home bar). */
--tg-safe-bottom: env(safe-area-inset-bottom, 0px);
--tg-safe-left: env(safe-area-inset-left, 0px);
--tg-safe-right: env(safe-area-inset-right, 0px);
and left/right edges by these so content clears the cut-outs (e.g. the gesture-nav home indicator
or the VK mobile home bar). */
--tg-safe-bottom: var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px));
--tg-safe-left: var(--safe-area-inset-left, env(safe-area-inset-left, 0px));
--tg-safe-right: var(--safe-area-inset-right, env(safe-area-inset-right, 0px));
--font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial,
"Noto Sans", "Liberation Sans", sans-serif;
--shadow: 0 1px 2px rgba(0, 0, 0, 0.08), 0 6px 16px rgba(0, 0, 0, 0.06);
+2 -1
View File
@@ -53,7 +53,8 @@
place-items: center;
/* Darker than the onboarding scrim — this blocks the board until the dictionary is ready. */
background: rgba(0, 0, 0, 0.72);
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
/* Via the shared --tg-safe-* tokens so the Android WebView < 140 env() bug is covered (app.css). */
padding: var(--tg-safe-top) var(--tg-safe-right) var(--tg-safe-bottom) var(--tg-safe-left);
}
.box {
display: grid;