feat: onboarding polish, splash screen, controller nav, dev script
Some checks failed
Build Archipelago ISO / build-iso (push) Has been cancelled
Build Archipelago ISO (dev) / build-iso (push) Failing after 45m15s

Onboarding flow:
- Intro: improved layout and transitions
- DID: better card styling and responsiveness
- Path: added visual enhancements
- Backup/Identity/Verify: streamlined markup
- SplashScreen component added

UI:
- Controller navigation improvements (useControllerNav)
- Style.css refinements

Backend:
- Runtime package fix

Dev:
- dev-start.sh improvements

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-28 13:41:52 +00:00
parent 82eeb915a3
commit 7f03e39f58
12 changed files with 92 additions and 67 deletions

View File

@@ -115,7 +115,14 @@ function findNearestInDirection(
scored.sort((a, b) => {
if (b.overlap !== a.overlap) return b.overlap - a.overlap
return a.dist - b.dist
if (a.dist !== b.dist) return a.dist - b.dist
// Tiebreaker for up/down: prefer leftmost element in grid layouts
if (direction === 'up' || direction === 'down') {
const aLeft = a.el.getBoundingClientRect().left
const bLeft = b.el.getBoundingClientRect().left
return aLeft - bLeft
}
return 0
})
return scored[0]?.el ?? null
}
@@ -149,7 +156,7 @@ export function useControllerNav(containerRef?: { value: HTMLElement | null }) {
const target = e.target as HTMLElement
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
// Enter in text field: blur and move to next focusable element (e.g., submit button)
// Enter in text field: find next focusable — if it's a button, click it directly (submit)
if (e.key === 'Enter' && target.tagName === 'INPUT' && (target as HTMLInputElement).type !== 'submit') {
e.preventDefault()
const root = containerRef?.value ?? document
@@ -157,12 +164,24 @@ export function useControllerNav(containerRef?: { value: HTMLElement | null }) {
const idx = all.indexOf(target as HTMLElement)
const next = idx >= 0 ? all[idx + 1] : undefined
if (next) {
next.focus()
next.scrollIntoView({ block: 'nearest', behavior: 'smooth' })
if (next.tagName === 'BUTTON' || next.getAttribute('role') === 'button') {
next.focus()
next.click()
} else {
next.focus()
next.scrollIntoView({ block: 'nearest', behavior: 'smooth' })
}
}
return
}
if (e.key !== 'Escape') return
// Up/Down arrows: exit field and navigate to element above/below
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
e.preventDefault()
;(target as HTMLElement).blur()
// Fall through to arrow key handling below
} else if (e.key !== 'Escape') {
return
}
}
const root = containerRef?.value ?? document