Skip to content

Commit 429a549

Browse files
committed
feat: implement keyboard visibility handling for mobile devices
- Added a utility function to check for focused editable elements. - Enhanced keyboard offset synchronization on mobile by responding to viewport resize and focus events. - Improved user experience by dynamically adjusting the layout based on keyboard visibility.
1 parent 303d083 commit 429a549

File tree

1 file changed

+33
-5
lines changed

1 file changed

+33
-5
lines changed

app/page.tsx

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,22 @@ const MODE_BUTTONS: Array<{ id: AppMode; icon: string; label: string }> = [
8282

8383
const TERMINAL_SPRING = { type: 'spring' as const, stiffness: 500, damping: 35 }
8484

85+
function hasFocusedEditableElement(): boolean {
86+
if (typeof document === 'undefined') return false
87+
const active = document.activeElement
88+
if (!active || !(active instanceof HTMLElement)) return false
89+
90+
if (active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement) {
91+
return !active.readOnly && !active.disabled
92+
}
93+
94+
if (active instanceof HTMLSelectElement) {
95+
return !active.disabled
96+
}
97+
98+
return active.isContentEditable || active.getAttribute('role') === 'textbox'
99+
}
100+
85101
export default function EditorLayout() {
86102
const { status } = useGateway()
87103
const { repo, setRepo } = useRepo()
@@ -162,12 +178,24 @@ export default function EditorLayout() {
162178
if (!isMobile) return
163179
const vv = window.visualViewport
164180
if (!vv) return
165-
const onResize = () => {
166-
const offset = window.innerHeight - vv.height
167-
setKeyboardOffset(offset > 50 ? offset : 0) // only respond to real keyboard
181+
182+
const syncKeyboardOffset = () => {
183+
const occludedHeight = Math.max(0, window.innerHeight - (vv.height + vv.offsetTop))
184+
const keyboardOpen = hasFocusedEditableElement() && occludedHeight > 80
185+
setKeyboardOffset(keyboardOpen ? occludedHeight : 0)
186+
}
187+
188+
syncKeyboardOffset()
189+
vv.addEventListener('resize', syncKeyboardOffset)
190+
vv.addEventListener('scroll', syncKeyboardOffset)
191+
document.addEventListener('focusin', syncKeyboardOffset)
192+
document.addEventListener('focusout', syncKeyboardOffset)
193+
return () => {
194+
vv.removeEventListener('resize', syncKeyboardOffset)
195+
vv.removeEventListener('scroll', syncKeyboardOffset)
196+
document.removeEventListener('focusin', syncKeyboardOffset)
197+
document.removeEventListener('focusout', syncKeyboardOffset)
168198
}
169-
vv.addEventListener('resize', onResize)
170-
return () => vv.removeEventListener('resize', onResize)
171199
}, [isMobile])
172200

173201
// ─── Auto-populate RepoContext from local git remote ───

0 commit comments

Comments
 (0)