fix(ui): keep PWA dialogs visible on Android (#1370)

* fix(ui): keep PWA dialogs visible on Android

The PWA dialog adjustments under
@media (display-mode: standalone) and (max-width: 768px) were originally
written to clear the iOS status bar / notch by adding a top offset and a
translateY override. The rule was not scoped to iOS, so Android PWAs
matched it too:

- The extra top: 50% + (safe-area-top * 0.22) plus
  --tw-translate-y: -50% + (safe-area-top * 0.6) pushed the dialog
  below the visible center on Android, where the parent already centers
  the popup via flex items-center justify-center on Base UI's portal.
- max-height was computed against 100vh. Android Chrome's collapsible
  URL bar makes 100vh larger than the visible viewport, so when the
  bar is shown the dialog's action buttons can be pushed off-screen
  (for example the Install button in the Skills install dialog).

Fix:

- Use 100dvh (with the existing safe-area subtractions) so max-height
  tracks the dynamic visible viewport on Android.
- Move the top / --tw-translate-y override into
  @supports (-webkit-touch-callout: none) so it only applies on iOS,
  where it was always intended.

Verified by rebuilding packages/web and inspecting the emitted CSS:
the common .pwa-dialog-content rule now ships with max-height using
100dvh and no top/translate overrides; the iOS-only block keeps the
original offsets.

Tested manually on Android Chrome PWA against
https://aion.xsim.uk: 'About OpenChamber' and 'Install skill' dialogs
now center vertically and their footer buttons stay on-screen as the
URL bar collapses/expands.

* fix(ui): restore vh fallback for PWA dialog max-height

Address review feedback on #1370: the previous patch dropped the
original `max-height: calc(100vh - ...)` line entirely and only kept
`100dvh`. On browsers that do not understand the `dvh` unit the
declaration is invalid and dropped, which would leave the dialog
without any `max-height` cap inside this media block — potentially
worse than before the fix.

Reinstate the canonical progressive-enhancement pattern: ship the
`100vh` declaration first so older engines have a usable value, then
override with `100dvh` on the next line for browsers that do support
it. New comment makes the two-line pattern explicit so it isn't pruned
again as accidental duplication.

Verified via `packages/web` build: the emitted CSS now contains both
declarations in order on the shared `.pwa-dialog-content` rule:

  max-height: calc(100vh - ...);
  max-height: calc(100dvh - ...);

`type-check` and `lint` in `packages/ui` remain clean.

---------

Co-authored-by: lilyzhaun <lilyzhaun@users.noreply.github.com>
This commit is contained in:
lilyzhaun
2026-05-24 14:19:19 +03:00
committed by GitHub
co-authored by lilyzhaun
parent 967704a9b9
commit 90b3d4760e
+26 -3
View File
@@ -385,11 +385,23 @@
@media (display-mode: standalone) and (max-width: 768px) {
.pwa-dialog-content {
--pwa-dialog-padding: clamp(0.75rem, 3vw, 1.25rem);
top: calc(50% + (var(--oc-safe-area-top, 0px) * 0.22));
max-height: calc(100vh - var(--oc-safe-area-top, 0px) - var(--oc-safe-area-bottom-visual, 0px) - 20px);
/* Browsers that don't understand dvh ignore the second declaration and
keep the vh-based fallback. Newer browsers use 100dvh so Android
Chrome's collapsible URL bar doesn't push the dialog footer off-screen. */
max-height: calc(
100vh
- var(--oc-safe-area-top, 0px)
- var(--oc-safe-area-bottom-visual, 0px)
- 20px
);
max-height: calc(
100dvh
- var(--oc-safe-area-top, 0px)
- var(--oc-safe-area-bottom-visual, 0px)
- 20px
);
padding: var(--pwa-dialog-padding);
padding-top: calc(var(--pwa-dialog-padding) + (var(--oc-safe-area-top, 0px) * 0.35));
--tw-translate-y: calc(-50% + (var(--oc-safe-area-top, 0px) * 0.6));
row-gap: clamp(0.75rem, 2vw, 1.25rem);
}
@@ -407,6 +419,17 @@
top: calc(0.2rem + (var(--oc-safe-area-top, 0px) * 0.3));
}
/* iOS-only: the original PWA dialog was offset down to clear the
status bar / notch. Android centers fine on its own and the extra
`top` + translate combo pushed dialogs (and their action buttons)
below the visible viewport, so keep this scoped to iOS. */
@supports (-webkit-touch-callout: none) {
.pwa-dialog-content {
top: calc(50% + (var(--oc-safe-area-top, 0px) * 0.22));
--tw-translate-y: calc(-50% + (var(--oc-safe-area-top, 0px) * 0.6));
}
}
.pwa-dialog-content .settings-page-body {
max-width: 100%;
padding: 0.75rem 1rem;