diff --git a/artifacts/tx-os/src/components/editable-cell.tsx b/artifacts/tx-os/src/components/editable-cell.tsx index 9c0b6205..b76105f5 100644 --- a/artifacts/tx-os/src/components/editable-cell.tsx +++ b/artifacts/tx-os/src/components/editable-cell.tsx @@ -545,9 +545,11 @@ function FormattingToolbar({ : "bg-white text-[#0B1E3F] hover:bg-gray-100 border border-gray-200"); // Position the toolbar via a portal so it escapes table cells with - // overflow:hidden. We try to place it above the editor, but flip below - // when there isn't enough room (e.g. first row of the table). We also - // clamp horizontally to keep it inside the viewport. + // overflow:hidden. Default placement is BELOW the editor; we only + // flip ABOVE when staying below would hide the toolbar under the iOS + // soft keyboard or off the bottom of the visible viewport (#581). + // We also clamp horizontally to keep it inside the table's scroll + // container (falling back to the viewport). const [pos, setPos] = useState<{ top: number; left: number } | null>(null); const [toolbarEl, setToolbarEl] = useState(null); const setToolbarNode = useCallback( @@ -595,7 +597,7 @@ function FormattingToolbar({ // swatches / Save / Cancel become unreachable on iPad. See #581. const vvTop = vv.offsetTop; const vvBottom = - vv.offsetTop + (vv.height || window.innerHeight); + vv.offsetTop + (vv.height ?? window.innerHeight); let top = rect.bottom + 4; if (top + tbHeight > vvBottom - 4) { const above = rect.top - tbHeight - 4;