Browse Source

refactor: update information sheet keyboard lift mechanism to use margin-bottom instead of transform and ensure focus visibility

master
mortezaei 2 weeks ago
parent
commit
a01fd26ef6
  1. 6
      src/components/Componentes/discount-widget.tsx
  2. 7
      src/components/Componentes/information-sheet.test.tsx
  3. 47
      src/components/Componentes/information-sheet.tsx

6
src/components/Componentes/discount-widget.tsx

@ -157,6 +157,12 @@ export function DiscountWidget({
dir="auto" dir="auto"
value={code} value={code}
disabled={discountStatus === "loading" || discountResult !== null} disabled={discountStatus === "loading" || discountResult !== null}
onFocus={(e) => {
const target = e.target;
setTimeout(() => {
target.scrollIntoView({ behavior: "smooth", block: "center" });
}, 150);
}}
onChange={(e) => { onChange={(e) => {
setCode(e.target.value); setCode(e.target.value);
if (discountStatus !== "initial") { if (discountStatus !== "initial") {

7
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", () => { it("should apply smooth keyboard lift when an input inside the sheet receives focus and keyboard height is set", () => {
const { container } = render(
render(
<InformationSheet <InformationSheet
isOpen={true} isOpen={true}
title="Payment Sheet" title="Payment Sheet"
@ -54,8 +54,7 @@ describe("InformationSheet", () => {
); );
}); });
// 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 () => { it("should reset keyboard lift when input loses focus", async () => {
@ -87,6 +86,6 @@ describe("InformationSheet", () => {
// Wait for focusout settlement // Wait for focusout settlement
await new Promise((r) => setTimeout(r, 60)); await new Promise((r) => setTimeout(r, 60));
expect(section?.style.transform).toBe("");
expect(section?.style.marginBottom).toBe("");
}); });
}); });

47
src/components/Componentes/information-sheet.tsx

@ -328,7 +328,7 @@ export function InformationSheet({
return; return;
} }
let currentKbHeight = 0;
let bridgeKbHeight = viewPaddingsBridge.getConfig().keyboardHeight || 0;
let hasFocusedInput = false; let hasFocusedInput = false;
const updateSheetLift = () => { const updateSheetLift = () => {
@ -339,28 +339,21 @@ export function InformationSheet({
? Math.max(0, window.innerHeight - visualViewport.height) ? Math.max(0, window.innerHeight - visualViewport.height)
: 0; : 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 = const effectiveHeight =
rawHeight > 20
? rawHeight
detectedHeight > 20
? detectedHeight
: hasFocusedInput : hasFocusedInput
? Math.round(window.innerHeight * 0.375)
? defaultHeight
: 0; : 0;
if (effectiveHeight > 20 && hasFocusedInput) { 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) { } else if (!hasFocusedInput) {
setKeyboardLift(0); setKeyboardLift(0);
} }
@ -373,6 +366,11 @@ export function InformationSheet({
) { ) {
hasFocusedInput = true; hasFocusedInput = true;
updateSheetLift(); 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) => { const unsubscribeConfig = viewPaddingsBridge.subscribeConfig((config) => {
currentKbHeight = config.keyboardHeight;
bridgeKbHeight = config.keyboardHeight;
updateSheetLift(); updateSheetLift();
}); });
@ -398,14 +396,16 @@ export function InformationSheet({
document.addEventListener("focusin", handleFocusIn); document.addEventListener("focusin", handleFocusIn);
document.addEventListener("focusout", handleFocusOut); document.addEventListener("focusout", handleFocusOut);
window.visualViewport?.addEventListener("resize", handleVpResize); window.visualViewport?.addEventListener("resize", handleVpResize);
window.visualViewport?.addEventListener("scroll", handleVpResize);
return () => { return () => {
document.removeEventListener("focusin", handleFocusIn); document.removeEventListener("focusin", handleFocusIn);
document.removeEventListener("focusout", handleFocusOut); document.removeEventListener("focusout", handleFocusOut);
window.visualViewport?.removeEventListener("resize", handleVpResize); window.visualViewport?.removeEventListener("resize", handleVpResize);
window.visualViewport?.removeEventListener("scroll", handleVpResize);
unsubscribeConfig(); unsubscribeConfig();
}; };
}, [isRendered, keyboardLift]);
}, [isRendered]);
if (!isRendered || !mounted) { if (!isRendered || !mounted) {
return null; return null;
@ -444,11 +444,8 @@ export function InformationSheet({
ref={sheetRef} ref={sheetRef}
{...props} {...props}
style={{ 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: maxHeight:
keyboardLift > 0 keyboardLift > 0
? `calc(100vh - ${keyboardLift + 20}px)` ? `calc(100vh - ${keyboardLift + 20}px)`

Loading…
Cancel
Save