fix: gamepad input field navigation — exit at cursor edges
- Up/Down from input: try containers as fallback when spatial nav fails - Left/Right from input: exit field when cursor is at start/end (e.g. Left from search bar at position 0 → category buttons) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ed9fd5c823
commit
7d61fc1790
@ -246,14 +246,38 @@ export function useControllerNav(containerRef?: { value: HTMLElement | null }) {
|
||||
if (nearest) {
|
||||
focusEl(nearest)
|
||||
} else {
|
||||
// Fallback: tab order when spatial navigation fails
|
||||
const idx = all.indexOf(target)
|
||||
const fallback = dir === 'down' ? all[idx + 1] : all[idx - 1]
|
||||
if (fallback) focusEl(fallback)
|
||||
// Spatial nav failed — try containers directly (e.g. search bar → first container)
|
||||
const containers = getContainers()
|
||||
const containerNearest = containers.length
|
||||
? findNearestInDirection(target, containers, dir)
|
||||
: null
|
||||
if (containerNearest) {
|
||||
focusEl(containerNearest)
|
||||
} else {
|
||||
// Last fallback: tab order
|
||||
const idx = all.indexOf(target)
|
||||
const fallback = dir === 'down' ? all[idx + 1] : all[idx - 1]
|
||||
if (fallback) focusEl(fallback)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
// Left/Right: stay in field (cursor movement). Escape: handled below.
|
||||
// Left/Right: cursor movement in field, but exit at edges
|
||||
if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
|
||||
const input = target as HTMLInputElement
|
||||
const atStart = input.selectionStart === 0 && input.selectionEnd === 0
|
||||
const atEnd = input.selectionStart === (input.value?.length ?? 0)
|
||||
if ((e.key === 'ArrowLeft' && atStart) || (e.key === 'ArrowRight' && atEnd)) {
|
||||
e.preventDefault()
|
||||
const dir = e.key === 'ArrowLeft' ? 'left' as const : 'right' as const
|
||||
const all = getFocusableElements(containerRef?.value ?? document)
|
||||
const candidates = all.filter(el => el !== target)
|
||||
const nearest = findNearestInDirection(target, candidates, dir)
|
||||
if (nearest) focusEl(nearest)
|
||||
}
|
||||
return
|
||||
}
|
||||
// Other keys (Escape): handled below.
|
||||
if (e.key !== 'Escape') return
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user