Browse Source

fix(coordinator): refine lift calculation to prevent overshooting top badge and add detailed geometry logging

master
mortezaei 20 hours ago
parent
commit
fb4c3ed60e
  1. 12
      src/app/globals.css
  2. 46
      src/components/Componentes/question-viewport-coordinator.ts

12
src/app/globals.css

@ -237,12 +237,12 @@ html:lang(ar) body,
}
}
body[data-page-background="none"] .app-shell {
background-image: none;
}
.app-shell:has(.page-background-none) {
background-image: none;
body[data-page-background="none"] .app-shell,
.app-shell:has(.page-background-none),
body:has(.page-background-none),
html:has(.page-background-none) {
background-image: none !important;
background-color: #F7F1F0 !important;
}
body[data-page-background="custom"] .app-shell {

46
src/components/Componentes/question-viewport-coordinator.ts

@ -29,11 +29,16 @@ const NON_KEYBOARD_INPUT_TYPES = new Set([
"submit",
]);
const DEFAULT_TOP_GAP = 28;
const DEFAULT_BOTTOM_GAP = 16;
export type QuestionLiftGeometry = {
baseTop: number;
baseBottom: number;
visibleTop: number;
visibleBottom: number;
topGap?: number;
bottomGap?: number;
gap?: number;
};
@ -42,18 +47,28 @@ export function computeQuestionLift({
baseBottom,
visibleTop,
visibleBottom,
topGap,
bottomGap,
gap = QUESTION_GAP,
}: QuestionLiftGeometry) {
const actualTopGap = topGap ?? gap ?? DEFAULT_TOP_GAP;
const actualBottomGap = bottomGap ?? gap ?? DEFAULT_BOTTOM_GAP;
const contentHeight = baseBottom - baseTop;
const availableTop = visibleTop + gap;
const availableBottom = visibleBottom - gap;
const availableTop = visibleTop + actualTopGap;
const availableBottom = visibleBottom - actualBottomGap;
const availableCenter = (availableTop + availableBottom) / 2;
const contentCenter = baseTop + contentHeight / 2;
const centerShift = Math.max(0, contentCenter - availableCenter);
const overlapShift = Math.max(0, baseBottom - availableBottom);
const maxShift = Math.max(0, baseTop - availableTop);
return Math.min(Math.max(centerShift, overlapShift), maxShift);
// When content is taller than available space, don't shove top to the extreme limit;
// prioritize keeping badge and title readable with comfortable top clearance.
const idealShift = contentHeight > (availableBottom - availableTop)
? Math.min(overlapShift, maxShift)
: Math.max(centerShift, overlapShift);
return Math.min(idealShift, maxShift);
}
function isKeyboardInputTarget(
@ -158,17 +173,30 @@ function updateLift() {
const safeTop = Number.parseFloat(
getComputedStyle(document.documentElement).getPropertyValue("--safe-top"),
);
const visibleTop = Math.max(
Number.isFinite(safeTop) ? safeTop : 0,
snapList?.getBoundingClientRect().top ?? 0,
);
const visibleBottom = Math.min(...visibleBottomCandidates);
const badgeEl = content.querySelector<HTMLElement>(
'.rounded-full.bg-\\[\\#F8D7DA\\]',
);
const badgeTop = badgeEl ? badgeEl.getBoundingClientRect().top : null;
const inputRect = activeQuestionInput?.getBoundingClientRect();
const computed = computeQuestionLift({
baseTop,
baseBottom,
visibleTop: Math.max(
Number.isFinite(safeTop) ? safeTop : 0,
snapList?.getBoundingClientRect().top ?? 0,
),
visibleBottom: Math.min(...visibleBottomCandidates),
visibleTop,
visibleBottom,
topGap: DEFAULT_TOP_GAP,
bottomGap: DEFAULT_BOTTOM_GAP,
});
console.log(`[Coord] computed lift: ${computed}px (baseTop: ${baseTop.toFixed(0)}, baseBottom: ${baseBottom.toFixed(0)}, kTop: ${keyboardTop?.toFixed(0)})`);
console.log(
`[Coord Geometry] lift: ${computed}px | content: [${baseTop.toFixed(0)}..${baseBottom.toFixed(0)}] h=${(baseBottom - baseTop).toFixed(0)} | vis: [${visibleTop.toFixed(0)}..${visibleBottom.toFixed(0)}] (kTop: ${keyboardTop?.toFixed(0)}) | badgeTop: ${badgeTop?.toFixed(0) ?? "none"} | input: [${inputRect?.top.toFixed(0) ?? "?"}..${inputRect?.bottom.toFixed(0) ?? "?"}]`,
);
setLift(computed);
}

Loading…
Cancel
Save