Remove global dialog adjustments for soft keyboard

Revert global CSS and JavaScript hooks that attempted to manage dialog positioning with the soft keyboard, which caused issues on desktop.
This commit is contained in:
Riyadh
2026-05-21 12:43:31 +00:00
parent 3a2e0d156b
commit 0bfad8a3a5
3 changed files with 18 additions and 63 deletions
+4 -4
View File
@@ -8,8 +8,10 @@ import { IncomingNotePopup } from "@/components/notes/incoming-note-popup";
import { useNotificationsSocket } from "@/hooks/use-notifications-socket"; import { useNotificationsSocket } from "@/hooks/use-notifications-socket";
import { useAudioUnlock } from "@/hooks/use-audio-unlock"; import { useAudioUnlock } from "@/hooks/use-audio-unlock";
import { useAutoplayHint } from "@/hooks/use-autoplay-hint"; import { useAutoplayHint } from "@/hooks/use-autoplay-hint";
import { useScrollFocusedDialogField } from "@/hooks/use-scroll-focused-dialog-field"; // #625-followup: the global keyboard hooks (useScrollFocusedDialogField,
import { useVisualViewportVars } from "@/hooks/use-visual-viewport-vars"; // useVisualViewportVars) were removed because they fired on touch-screen
// laptops too and broke desktop dialog layout. A more targeted approach
// will replace them.
import { UpcomingMeetingAlert } from "@/components/executive-meetings/upcoming-meeting-alert"; import { UpcomingMeetingAlert } from "@/components/executive-meetings/upcoming-meeting-alert";
import { PushEnablePrompt } from "@/components/push-enable-prompt"; import { PushEnablePrompt } from "@/components/push-enable-prompt";
import NotFound from "@/pages/not-found"; import NotFound from "@/pages/not-found";
@@ -48,8 +50,6 @@ function NotificationsSocketBridge() {
useNotificationsSocket(); useNotificationsSocket();
useAudioUnlock(); useAudioUnlock();
useAutoplayHint(); useAutoplayHint();
useScrollFocusedDialogField();
useVisualViewportVars();
return null; return null;
} }
+10 -52
View File
@@ -470,58 +470,16 @@ html[dir="rtl"] .truncate {
} }
/* /*
* Dialog keyboard-aware sheet override (touch devices only). * (Reverted) Earlier attempts (#622, #623, #624) added a global
* * `[role="dialog"]:has(:focus)` override + companion JS hooks to keep
* History: #622/#623 tried two earlier strategies — pinning the dialog * the focused field above the iOS soft keyboard. Each iteration
* via a `:has(:focus)` rule sized with `100dvh`, and a JS scroll hook * regressed desktop browsers — on a touch-screen laptop the rule
* — both kept the focused field hidden behind the iOS keyboard. Two * fired on every input focus and broke Radix dialog layout (narrow
* facts made that approach unfixable: * strip in the top-left). The rule, the helper class
* 1) Safari iOS/iPadOS ignores `interactive-widget=resizes-content`, * (`.dialog-vv-wrapper`), and the global hooks are removed here.
* so `100dvh` does NOT shrink when the keyboard opens. The rule * Dialogs now render with their original Radix / consumer styles on
* fired but the height it used was always the full screen, so the * every device. The iOS keyboard issue will be revisited with a
* dialog still ran behind the keyboard. * targeted, per-dialog approach instead of a global override.
* 2) The rule was also unconditional. On desktop, focusing any input
* inside a Radix `DialogContent` instantly stretched the dialog
* to `width:100vw top:0`, colliding with Radix's open-state slide
* animation transforms and rendering the dialog as a broken strip
* pinned in the top-left corner.
*
* Fix:
* • Gate the rule with `@media (any-pointer: coarse)` so the desktop
* case is untouched.
* • Drive the size from `--vv-height` / `--vv-offset-top` — CSS
* variables that `useVisualViewportVars` (in App.tsx) updates from
* `window.visualViewport` on every keyboard / chrome / orientation
* change. `visualViewport` is the one signal iOS does keep
* accurate, including in standalone PWAs.
* • Fall back to `100vh` / `0` when the vars haven't been written
* yet (first paint, or on browsers without `visualViewport`).
*
* `.dialog-vv-wrapper` is for full-screen overlay wrappers (used by
* `AdminFormDialog` and similar bespoke modals) where `role="dialog"`
* sits on a NON-fixed inner card. Adding the class to the outer
* `position: fixed` overlay makes IT shrink with the keyboard, so the
* inner card — centred inside it — stays in the visible band.
*/ */
@media (any-pointer: coarse) {
[role="dialog"]:has(:is(input, textarea, select, [contenteditable="true"]):focus) {
top: var(--vv-offset-top, 0px) !important;
left: 0 !important;
right: 0 !important;
bottom: auto !important;
width: 100vw !important;
max-width: none !important;
max-height: var(--vv-height, 100vh) !important;
transform: none !important;
overflow-y: auto !important;
-webkit-overflow-scrolling: touch !important;
}
.dialog-vv-wrapper {
top: var(--vv-offset-top, 0px) !important;
bottom: auto !important;
height: var(--vv-height, 100vh) !important;
}
}
+4 -7
View File
@@ -418,7 +418,7 @@ function AdminFormDialog({
return () => window.removeEventListener("keydown", handleKey); return () => window.removeEventListener("keydown", handleKey);
}, [isPending, onCancel]); }, [isPending, onCancel]);
return ( return (
<div className="fixed inset-x-0 top-0 h-screen bg-slate-900/50 backdrop-blur-sm z-50 flex items-center justify-center p-3 sm:p-4 dialog-vv-wrapper"> <div className="fixed inset-0 bg-slate-900/50 backdrop-blur-sm z-50 flex items-center justify-center p-3 sm:p-4">
<div <div
className={cn( className={cn(
// Solid white surface instead of the heavy glass panel — // Solid white surface instead of the heavy glass panel —
@@ -426,10 +426,7 @@ function AdminFormDialog({
// invisible (see #616-followup screenshot). Keep the soft // invisible (see #616-followup screenshot). Keep the soft
// shadow + rounded look so it still feels like the rest of // shadow + rounded look so it still feels like the rest of
// the OS surface. // the OS surface.
// `max-h-full` (not `90vh`) so on touch devices, when the "bg-white rounded-2xl sm:rounded-3xl w-full overflow-hidden shadow-2xl ring-1 ring-slate-200 flex flex-col max-h-[90vh]",
// outer `dialog-vv-wrapper` shrinks to the keyboard-free
// band, this card shrinks with it instead of overflowing.
"bg-white rounded-2xl sm:rounded-3xl w-full overflow-hidden shadow-2xl ring-1 ring-slate-200 flex flex-col max-h-full",
widthClass, widthClass,
)} )}
role="dialog" role="dialog"
@@ -3331,13 +3328,13 @@ function DrillInShell({
}, [onClose]); }, [onClose]);
return ( return (
<div <div
className="fixed inset-x-0 top-0 h-screen bg-slate-900/30 backdrop-blur-sm z-50 flex items-center justify-center p-4 dialog-vv-wrapper" className="fixed inset-0 bg-slate-900/30 backdrop-blur-sm z-50 flex items-center justify-center p-4"
role="dialog" role="dialog"
aria-modal="true" aria-modal="true"
onClick={onClose} onClick={onClose}
> >
<div <div
className="glass-panel rounded-3xl p-5 w-full max-w-md max-h-full flex flex-col gap-3" className="glass-panel rounded-3xl p-5 w-full max-w-md max-h-[85vh] flex flex-col gap-3"
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
<div className="flex items-start justify-between gap-3"> <div className="flex items-start justify-between gap-3">