From a01fd26ef6478bef80d39f87d54a74f701c6e842 Mon Sep 17 00:00:00 2001 From: mortezaei Date: Sun, 30 Aug 2026 21:45:29 +0330 Subject: [PATCH] refactor: update information sheet keyboard lift mechanism to use margin-bottom instead of transform and ensure focus visibility --- .../Componentes/discount-widget.tsx | 6 +++ .../Componentes/information-sheet.test.tsx | 7 ++- .../Componentes/information-sheet.tsx | 47 +++++++++---------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/components/Componentes/discount-widget.tsx b/src/components/Componentes/discount-widget.tsx index e35e1d2..c91b116 100644 --- a/src/components/Componentes/discount-widget.tsx +++ b/src/components/Componentes/discount-widget.tsx @@ -157,6 +157,12 @@ export function DiscountWidget({ dir="auto" value={code} disabled={discountStatus === "loading" || discountResult !== null} + onFocus={(e) => { + const target = e.target; + setTimeout(() => { + target.scrollIntoView({ behavior: "smooth", block: "center" }); + }, 150); + }} onChange={(e) => { setCode(e.target.value); if (discountStatus !== "initial") { diff --git a/src/components/Componentes/information-sheet.test.tsx b/src/components/Componentes/information-sheet.test.tsx index 50e79b6..66ab292 100644 --- a/src/components/Componentes/information-sheet.test.tsx +++ b/src/components/Componentes/information-sheet.test.tsx @@ -23,7 +23,7 @@ describe("InformationSheet", () => { }); it("should apply smooth keyboard lift when an input inside the sheet receives focus and keyboard height is set", () => { - const { container } = render( + render( { ); }); - // Verify section transform is applied or calculated - expect(section).toBeDefined(); + expect(section?.style.marginBottom).toBe("280px"); }); it("should reset keyboard lift when input loses focus", async () => { @@ -87,6 +86,6 @@ describe("InformationSheet", () => { // Wait for focusout settlement await new Promise((r) => setTimeout(r, 60)); - expect(section?.style.transform).toBe(""); + expect(section?.style.marginBottom).toBe(""); }); }); diff --git a/src/components/Componentes/information-sheet.tsx b/src/components/Componentes/information-sheet.tsx index 42687c8..5d3b1ae 100644 --- a/src/components/Componentes/information-sheet.tsx +++ b/src/components/Componentes/information-sheet.tsx @@ -328,7 +328,7 @@ export function InformationSheet({ return; } - let currentKbHeight = 0; + let bridgeKbHeight = viewPaddingsBridge.getConfig().keyboardHeight || 0; let hasFocusedInput = false; const updateSheetLift = () => { @@ -339,28 +339,21 @@ export function InformationSheet({ ? Math.max(0, window.innerHeight - visualViewport.height) : 0; - const rawHeight = Math.max(currentKbHeight, vpReduction); + const detectedHeight = Math.max(bridgeKbHeight, vpReduction); + const defaultHeight = + typeof window !== "undefined" && window.innerHeight > 0 + ? Math.round(window.innerHeight * 0.375) + : 285; + const effectiveHeight = - rawHeight > 20 - ? rawHeight + detectedHeight > 20 + ? detectedHeight : hasFocusedInput - ? Math.round(window.innerHeight * 0.375) + ? defaultHeight : 0; if (effectiveHeight > 20 && hasFocusedInput) { - const rect = sheetRef.current.getBoundingClientRect(); - const safeTop = - parseFloat( - getComputedStyle(document.documentElement).getPropertyValue( - "--safe-top", - ) || "0", - ) || 16; - const availableTop = Math.max(0, rect.top - safeTop - 8); - const lift = Math.min( - effectiveHeight, - availableTop + (keyboardLift || 0), - ); - setKeyboardLift(Math.max(0, Math.round(lift))); + setKeyboardLift(Math.round(effectiveHeight)); } else if (!hasFocusedInput) { setKeyboardLift(0); } @@ -373,6 +366,11 @@ export function InformationSheet({ ) { hasFocusedInput = true; updateSheetLift(); + setTimeout(() => { + if (e.target instanceof HTMLElement) { + e.target.scrollIntoView({ behavior: "smooth", block: "center" }); + } + }, 150); } }; @@ -387,7 +385,7 @@ export function InformationSheet({ }; const unsubscribeConfig = viewPaddingsBridge.subscribeConfig((config) => { - currentKbHeight = config.keyboardHeight; + bridgeKbHeight = config.keyboardHeight; updateSheetLift(); }); @@ -398,14 +396,16 @@ export function InformationSheet({ document.addEventListener("focusin", handleFocusIn); document.addEventListener("focusout", handleFocusOut); window.visualViewport?.addEventListener("resize", handleVpResize); + window.visualViewport?.addEventListener("scroll", handleVpResize); return () => { document.removeEventListener("focusin", handleFocusIn); document.removeEventListener("focusout", handleFocusOut); window.visualViewport?.removeEventListener("resize", handleVpResize); + window.visualViewport?.removeEventListener("scroll", handleVpResize); unsubscribeConfig(); }; - }, [isRendered, keyboardLift]); + }, [isRendered]); if (!isRendered || !mounted) { return null; @@ -444,11 +444,8 @@ export function InformationSheet({ ref={sheetRef} {...props} style={{ - transform: - keyboardLift > 0 - ? `translate3d(0, -${keyboardLift}px, 0)` - : undefined, - transition: "transform 200ms cubic-bezier(0.16, 1, 0.3, 1)", + marginBottom: keyboardLift > 0 ? `${keyboardLift}px` : undefined, + transition: "margin-bottom 200ms cubic-bezier(0.16, 1, 0.3, 1)", maxHeight: keyboardLift > 0 ? `calc(100vh - ${keyboardLift + 20}px)`