diff --git a/artifacts/tx-os/src/components/notes/send-note-dialog.tsx b/artifacts/tx-os/src/components/notes/send-note-dialog.tsx index e7faefc5..9c656115 100644 --- a/artifacts/tx-os/src/components/notes/send-note-dialog.tsx +++ b/artifacts/tx-os/src/components/notes/send-note-dialog.tsx @@ -1,6 +1,7 @@ import { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Check, Search, Send } from "lucide-react"; +import { useVisualViewport } from "@/hooks/use-visual-viewport"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; @@ -42,6 +43,24 @@ export function SendNoteDialog({ const send = useSendNote(); const [search, setSearch] = useState(""); const [picked, setPicked] = useState>(new Set()); + // Make the recipients list shrink to fit when the iPad soft keyboard + // takes over the bottom half of the screen. Without this the dialog + // keeps its full height, gets centred under the keyboard, and the + // people list ends up hidden — same root cause as #581 / the toolbar + // fix in editable-cell.tsx (visualViewport excludes the keyboard but + // not the QuickType strip, so we add a 48px buffer when the keyboard + // is up). + const vv = useVisualViewport(); + const KEYBOARD_PREDICTION_INSET = vv.keyboardInset > 0 ? 48 : 0; + const listMaxHeight = (() => { + const usable = (vv.height || window.innerHeight) - KEYBOARD_PREDICTION_INSET; + // Reserve ~220px for the dialog chrome (title + search input + + // footer + paddings) so the list never pushes the buttons off + // screen. Clamp to a sensible min/max so desktop keeps the old + // 288px (max-h-72) feel. + const forList = Math.max(120, Math.min(288, usable - 220)); + return forList; + })(); const candidates = useMemo(() => { const me = user?.id; @@ -121,7 +140,10 @@ export function SendNoteDialog({ data-testid="send-note-search" /> -
+
{isLoading && (
{t("common.loading", "Loading...")}