fix(mobile): split CJK keyboard positioning by device size

Phones use translateY(-keyboardOffset) — CSS bottom is relative to layout
viewport and keyboardOffset reliably lifts it above the keyboard (iOS
doesn't auto-scroll the visual viewport for the CJK textarea on phones).

iPad uses direct bottom positioning from keyboard height — translateY
broke because iOS auto-scrolls the visual viewport when the CJK textarea
receives focus, making keyboardOffset approach 0.
This commit is contained in:
Teigen
2026-06-17 23:40:04 +08:00
parent c55af9ec39
commit cd7d8c7329
+19 -8
View File
@@ -326,15 +326,26 @@ const KeyboardHandler = {
} }
} }
// CJK textarea: position on ALL touch devices (it's always position:fixed). // CJK textarea positioning (always position:fixed on touch devices).
// Uses keyboard HEIGHT directly — independent of visualViewport.offsetTop
// which iOS adjusts when the CJK textarea receives focus/dictation.
if (cjkInput?.classList.contains('cjk-input-visible') && keyboardHeight > 0) { if (cjkInput?.classList.contains('cjk-input-visible') && keyboardHeight > 0) {
// On phones, sit above toolbar+accessory (84px). On tablets in normal if (isSmallMedium) {
// flow, the toolbar/accessory are in-flow so use a smaller offset. // Phones: use translateY like toolbar/accessory bar. The CSS bottom
const bottomOffset = isSmallMedium ? 84 : 44; // (84px) is relative to the layout viewport; translateY lifts it
cjkInput.style.bottom = `${keyboardHeight + bottomOffset}px`; // above the keyboard. This works on phones where iOS doesn't
cjkInput.style.transform = ''; // auto-scroll the visual viewport for the CJK textarea.
const layoutHeight = window.innerHeight;
const visualBottom = window.visualViewport.offsetTop + window.visualViewport.height;
const keyboardOffset = Math.max(0, layoutHeight - visualBottom);
cjkInput.style.transform = keyboardOffset > 0 ? `translateY(${-keyboardOffset}px)` : '';
cjkInput.style.bottom = '';
} else {
// iPad: use direct bottom positioning from keyboard height.
// translateY breaks on iPad because iOS auto-scrolls the visual
// viewport when the CJK textarea receives focus, making
// keyboardOffset unreliable (approaches 0).
cjkInput.style.bottom = `${keyboardHeight + 44}px`;
cjkInput.style.transform = '';
}
} }
} else { } else {
this.resetLayout(); this.resetLayout();