feat(ux): UX16 — autofocus the URL field on launch

An App mount effect focuses #aerofetch-url when the Downloads tab is active
(double-rAF for paint), so a user can paste + type immediately instead of
clicking first.

typecheck + eslint + prettier green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 11:35:44 -04:00
parent ab825488b8
commit cc4fb132e4
2 changed files with 13 additions and 1 deletions
+3 -1
View File
@@ -1170,8 +1170,10 @@ root cause is already filed.
### Low — polish & smaller friction
- [ ] **UX16 — URL field isn't focused on launch.** `aerofetch-url` is only focused via the command
- [x] **UX16 — URL field isn't focused on launch.** `aerofetch-url` is only focused via the command
palette; opening the app or the Downloads tab requires a click to start typing. **Fix:** autofocus it.
*Fixed: an `App` mount effect focuses `#aerofetch-url` on launch when the Downloads tab is active
(double-rAF for paint, reusing the command palette's focus pattern).*
- [ ] **UX17 — Icon-only Fetch/Paste buttons** rely on hover tooltips for meaning (UI a11y; new users on touch/keyboard miss them). **Fix:** labels or `aria`-described affordances.
- [ ] **UX18 — The quality control morphs after Fetch** (preset list → real formats; label "Quality" →
"Quality / format") in place — a surprising transform. **Fix:** keep a stable control with a clear "formats loaded" state.
+10
View File
@@ -104,6 +104,16 @@ function App(): React.JSX.Element {
useDownloads.getState().hydrate()
}, [])
// UX16: focus the URL field on launch so the user can paste + type immediately
// (Downloads is the default tab). Double-rAF waits for paint, matching the command
// palette's "New download" focus.
useEffect(() => {
if (useNav.getState().tab !== 'downloads') return
requestAnimationFrame(() =>
requestAnimationFrame(() => document.getElementById('aerofetch-url')?.focus())
)
}, [])
// Promote scheduled ('saved' + a due scheduledFor) items when their time arrives.
// The queue is persisted (M4), so a scheduled item survives a quit and fires on the
// next launch once its time has passed. A 15s tick is plenty for minute-granularity