Skip to content

Browser back/forward for view navigation #29

Open

Description

@JackCuthbert

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:

  • selectList also calls history.pushState({ view }, '', urlFor(view))
  • a popstate listener sets state from event.state
  • on load, seed from the URL when there is a path, else localStorage as 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 localStorage last 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 sheet mode, 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 localStorage precedence on a cold load with no path. Probably: URL if present, else persisted, else Today.
  • Does pushState or replaceState apply 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestneeds-specNeeds a design/spec before implementation

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions