fix(builder): mobile-A2 hardening -- 16px inputs, shared sheet/modal chrome, z-scale + portal
- Force font-size:16px !important on Styles-sheet/topbar/Sitesmith inputs inside the mobile media query so inline 12px/14px styles stop triggering iOS zoom-on-focus. - Lift sheet-open + Templates/Head Code modal-open state out of private useState into a shared MobileChromeContext (EditorShell), so Phase B can open/close sheets from outside MobilePanelBar. - Add an explicit z-index layer scale, portal TemplateModal to document.body (was trapped under the tab bar inside .topbar's stacking context), align Sitesmith to the same --z-modal layer, and make opening a sheet close any open modal. Also fix modal backdrops swallowing tab bar taps (mirrors the sheet backdrop's existing tab-bar cutout). - Drop BottomSheet's incorrect aria-modal; mobile-aware AssetsPanel empty state copy. - Tests: useIsMobile (matchMedia mock incl. legacy fallback + cleanup), MobileChromeContext invariants (one sheet open, sheet closes modals), MobilePanelBar wiring. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,24 @@
|
||||
/* Phase A (mobile): fixed bottom tab bar height, used to size
|
||||
.editor-container and the safe-area padding math below. */
|
||||
--mobile-tabbar-height: 58px;
|
||||
|
||||
/* Mobile-A2: explicit overlay layer scale (was ad-hoc numbers scattered
|
||||
across the mobile block + Modal.tsx, causing accidental stacking --
|
||||
e.g. the Templates modal getting trapped under the tab bar inside
|
||||
.topbar's own stacking context). Higher = closer to the user.
|
||||
--z-selection-toolbar is reserved for Phase B's selection toolbar. */
|
||||
--z-sheet-backdrop: 400;
|
||||
--z-tabbar: 500;
|
||||
--z-selection-toolbar: 600;
|
||||
--z-modal: 5000;
|
||||
--z-overflow: 10000;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Modals (shared by Modal.tsx -- TemplateModal, HeadCodeModal, SitesmithModal)
|
||||
-------------------------------------------------------------------------- */
|
||||
.modal-backdrop {
|
||||
z-index: var(--z-modal);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
@@ -1459,6 +1477,23 @@ body {
|
||||
border-color: var(--color-accent);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
Full-screen modals (Modal.tsx -- TemplateModal/HeadCodeModal/
|
||||
SitesmithModal share `.modal-backdrop`). Same tab-bar cutout as
|
||||
`.mobile-sheet-backdrop` below, and for the same reason: without it,
|
||||
the backdrop's default `inset: 0` sits ABOVE the tab bar (--z-modal >
|
||||
--z-tabbar) and swallows every tap there, so "open Templates -> tap a
|
||||
bottom tab" would silently just close Templates (a tap on the
|
||||
backdrop) instead of ALSO opening the tapped sheet. `!important`
|
||||
because Modal.tsx sets `bottom` via an inline style, which otherwise
|
||||
beats this class rule. The modal's own content still sits above the
|
||||
tab bar (it's a commit/cancel moment) -- only the dismiss-affordance
|
||||
backdrop stops short, exactly like the sheet backdrop.
|
||||
-------------------------------------------------------------------- */
|
||||
.modal-backdrop {
|
||||
bottom: calc(var(--mobile-tabbar-height) + env(safe-area-inset-bottom, 0px)) !important;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
"⋯" overflow menu (TopBarOverflowMenu.tsx)
|
||||
-------------------------------------------------------------------- */
|
||||
@@ -1466,7 +1501,7 @@ body {
|
||||
position: fixed;
|
||||
top: calc(var(--topbar-height) + env(safe-area-inset-top, 0px) + 6px);
|
||||
right: calc(8px + env(safe-area-inset-right, 0px));
|
||||
z-index: 10000;
|
||||
z-index: var(--z-overflow);
|
||||
min-width: 220px;
|
||||
max-width: calc(100vw - 16px);
|
||||
max-height: calc(100dvh - var(--topbar-height) - 24px);
|
||||
@@ -1557,7 +1592,7 @@ body {
|
||||
directly, instead of requiring a close-then-reopen round trip. The
|
||||
backdrop itself stops short of the tab bar (see its `bottom` offset
|
||||
below) so this is mostly belt-and-suspenders for the boundary. */
|
||||
z-index: 500;
|
||||
z-index: var(--z-tabbar);
|
||||
display: flex;
|
||||
height: calc(var(--mobile-tabbar-height) + env(safe-area-inset-bottom, 0px));
|
||||
background: var(--color-bg-surface);
|
||||
@@ -1605,7 +1640,7 @@ body {
|
||||
being swallowed by the overlay sitting on top of it. */
|
||||
bottom: calc(var(--mobile-tabbar-height) + env(safe-area-inset-bottom, 0px));
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 400;
|
||||
z-index: var(--z-sheet-backdrop);
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
@@ -1679,6 +1714,13 @@ body {
|
||||
Touch ergonomics inside sheets -- 16px inputs kill iOS's auto-zoom on
|
||||
focus; touch-action speeds up tap response on chrome that doesn't need
|
||||
native scroll-gesture handling.
|
||||
|
||||
`!important` is required here: GuidedStyles/StylePanel inputs (see
|
||||
`inputStyle` in `panels/right/styles/shared.tsx`) carry an INLINE
|
||||
`font-size: 12px`, which otherwise beats this class rule on the
|
||||
Styles sheet -- the most-used mobile surface -- and iOS zooms in on
|
||||
focus. `.sitesmith-textarea` (ChatInput.tsx, inline font-size: 14)
|
||||
has the same problem even though the Sitesmith modal isn't a sheet.
|
||||
-------------------------------------------------------------------- */
|
||||
.mobile-sheet-body button,
|
||||
.mobile-sheet-body .block-item {
|
||||
@@ -1693,8 +1735,9 @@ body {
|
||||
.control-select,
|
||||
.topbar input,
|
||||
.topbar textarea,
|
||||
.topbar select {
|
||||
font-size: 16px;
|
||||
.topbar select,
|
||||
.sitesmith-textarea {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
.mobile-sheet-body .settings-tabs button {
|
||||
|
||||
Reference in New Issue
Block a user