Fix dialog display issues when the on-screen keyboard is active
Adjust dialog positioning on iOS Safari to render as a full-width sheet when the keyboard is open, preventing layout shifts and ensuring content remains visible.
This commit is contained in:
@@ -41,23 +41,32 @@ const DialogContent = React.forwardRef<
|
|||||||
const keyboardOpen = keyboardInset > 80
|
const keyboardOpen = keyboardInset > 80
|
||||||
const dynamicStyle: React.CSSProperties = keyboardOpen
|
const dynamicStyle: React.CSSProperties = keyboardOpen
|
||||||
? {
|
? {
|
||||||
// Anchor the dialog to the TOP of the visible visual viewport
|
// Mobile-sheet behaviour when an on-screen keyboard is open.
|
||||||
// (right under the iOS status bar) and let it take the full
|
|
||||||
// available height above the keyboard. Anchoring (vs centering)
|
|
||||||
// is critical for tall forms — when the dialog is centered and
|
|
||||||
// the form has many fields, the footer slides into the middle
|
|
||||||
// of the visible area and the bottom half of the form ends up
|
|
||||||
// hidden behind the keyboard. With top-anchor + maxHeight, the
|
|
||||||
// dialog's own flex column (header / scrollable middle /
|
|
||||||
// footer) keeps Save/Cancel pinned above the keyboard and the
|
|
||||||
// rest of the form scrolls inside.
|
|
||||||
//
|
//
|
||||||
// The override of `transform` is necessary because the class
|
// The base className puts the dialog at left:50%+translateX(-50%)
|
||||||
// string below applies `translate-y-[-50%]`; we need to keep
|
// (horizontal centering) and top:50%+translateY(-50%) (vertical
|
||||||
// the horizontal centering but cancel the vertical one.
|
// centering). On iOS Safari with the soft keyboard open the
|
||||||
|
// layout viewport and the visual viewport diverge in BOTH axes
|
||||||
|
// (visualViewport.offsetLeft, .pageLeft and zoom factor can all
|
||||||
|
// shift), which made our previous "top-anchor + translateX(-50%)"
|
||||||
|
// override render as a narrow column shoved against one edge of
|
||||||
|
// the screen.
|
||||||
|
//
|
||||||
|
// To sidestep all of that we drop the centering entirely while
|
||||||
|
// the keyboard is open and pin the dialog as a top-anchored
|
||||||
|
// full-width sheet: explicit left/right insets, no transform,
|
||||||
|
// width:auto so the consumer's `w-[calc(100vw-1rem)]` or
|
||||||
|
// `max-w-3xl` no longer drive horizontal position. The
|
||||||
|
// dialog's internal `flex flex-col` (header / scrollable middle
|
||||||
|
// / sticky footer) then keeps Save/Cancel pinned above the
|
||||||
|
// keyboard and the rest of the form scrolls inside.
|
||||||
top: `${offsetTop}px`,
|
top: `${offsetTop}px`,
|
||||||
|
left: "8px",
|
||||||
|
right: "8px",
|
||||||
|
width: "auto",
|
||||||
|
maxWidth: "none",
|
||||||
maxHeight: `${height - 8}px`,
|
maxHeight: `${height - 8}px`,
|
||||||
transform: "translateX(-50%)",
|
transform: "none",
|
||||||
...style,
|
...style,
|
||||||
}
|
}
|
||||||
: (style ?? {})
|
: (style ?? {})
|
||||||
|
|||||||
Reference in New Issue
Block a user