feat(FN-959): add --overlay-padding-top CSS variable to reposition modal on mobile keyboard open

- Add --overlay-padding-top CSS custom property to modal overlay styles
- Update TerminalModal component to apply dynamic padding-top when mobile keyboard is detected
- Add regression tests verifying overlay padding-top behavior with keyboard events
This commit is contained in:
gsxdsm
2026-04-05 11:19:38 -07:00
parent 23f74e60db
commit 169acbc7a2
3 changed files with 46 additions and 1 deletions

View File

@@ -538,6 +538,13 @@ export function TerminalModal({ isOpen, onClose, initialCommand }: TerminalModal
className="modal-overlay open"
onClick={handleOverlayClick}
data-testid="terminal-modal-overlay"
style={
keyboardOverlap > 0
? {
"--overlay-padding-top": "0px",
} as React.CSSProperties
: undefined
}
>
<div
ref={modalRef}

View File

@@ -1769,6 +1769,44 @@ describe("TerminalModal — virtual keyboard overlap handling", () => {
expect(scrollIntoViewSpy).not.toHaveBeenCalled();
});
it("sets --overlay-padding-top on overlay when keyboard overlap is detected", async () => {
simulateMobileDevice(250);
render(<TerminalModal isOpen={true} onClose={mockOnClose} />);
await waitFor(() => {
const overlay = screen.getByTestId("terminal-modal-overlay");
expect(overlay.style.getPropertyValue("--overlay-padding-top")).toBe("0px");
});
});
it("clears --overlay-padding-top from overlay when keyboard closes", async () => {
const { listeners, mockVV } = simulateMobileDevice(250);
render(<TerminalModal isOpen={true} onClose={mockOnClose} />);
await waitFor(() => {
const overlay = screen.getByTestId("terminal-modal-overlay");
expect(overlay.style.getPropertyValue("--overlay-padding-top")).toBe("0px");
});
// Keyboard closes → visualViewport.height returns to full height (550 = innerHeight)
Object.defineProperty(mockVV, "height", {
value: 550,
writable: true,
configurable: true,
});
act(() => {
for (const cb of listeners.resize) cb();
});
await waitFor(() => {
const overlay = screen.getByTestId("terminal-modal-overlay");
expect(overlay.style.getPropertyValue("--overlay-padding-top")).toBe("");
});
});
});
// --- Close/reopen regression tests ---

View File

@@ -2582,7 +2582,7 @@ body {
z-index: 100;
justify-content: center;
align-items: flex-start;
padding-top: 10vh;
padding-top: var(--overlay-padding-top, 10vh);
}
.modal-overlay.open {
display: flex;