Repository navigation
Browser back/forward for view navigation #29
Description
Switching views is now common enough — the grouped grocery/health rows in Today navigate to their list on click (#27) — that the browser's back button not working is a real annoyance. You press it expecting to return to Today and leave the app instead.
Browser history, not an in-app back/forward. An in-app pair would mean building a history stack the browser already provides, and it would not fix the muscle memory that makes this annoying in the first place.
Why this is smaller than it sounds
There is no router, and this doesn't need one. Selection is a single useState in main-screen.tsx persisted to localStorage, and selectList is already the one choke point every view change goes through — the nav rows, the keyboard chords, the grouped rows, and the "follow the todo to the list it landed in" behaviour after a global add.
So the shape is roughly:
selectListalso callshistory.pushState({ view }, '', urlFor(view))- a
popstatelistener sets state fromevent.state - on load, seed from the URL when there is a path, else
localStorageas today
A router (react-router et al) would be a large dependency, a route table and a set of data-loading conventions to solve a one-variable problem. Worth revisiting only if the app grows a second navigational axis.
The payoff beyond back
- Real URLs —
/today,/summary,/list/<id>— so a view can be bookmarked and a link shared. - Reload lands where you were, rather than on whatever
localStoragelast held. - Forward works too, for free.
Worth settling first
- Does opening a todo push history? My instinct is no: back should leave the view, not close the detail panel. But it is genuinely arguable on mobile, where the panel is a full-screen sheet and back is exactly the gesture people reach for to dismiss it. Possibly the honest answer is that it pushes only in
sheetmode, which is a real behavioural split and needs deciding rather than falling out of the implementation. - What else is navigational? Deliberately not: modals (Settings, Help, New todo/list), the nav's collapsed state, the Completed accordion. Back closing a modal is a common and disliked behaviour. Each of these is a decision, not an oversight, and the issue should say so.
- List ids in URLs. They are CalDAV collection href segments — URL-safe but opaque, and they change if a list is deleted and recreated. A stale bookmark should land on Today via the existing "persisted list no longer exists" fallback (
main-screen.tsx), which already handles precisely this. - URL vs
localStorageprecedence on a cold load with no path. Probably: URL if present, else persisted, else Today. - Does
pushStateorreplaceStateapply when the app follows a todo to its list after a global add? Pushing there means back undoes a navigation the user did not consciously make.
Not this issue
- No router adoption. If this turns out to need one, that is a separate decision with its own argument.
- No deep links into a todo.
/list/<id>/todo/<uid>is a bigger surface — it has to handle a uid that no longer exists, and it interacts with the "does the panel push history" question above. Views first. - No scroll restoration.
Pairs with
#26 (command palette) — both are about moving around the app quickly, and a palette that jumps to a list wants the same selectList seam this issue formalises. Worth doing this one first: it is smaller, and the palette then inherits working history for free.
Activity